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.
- cancan_microstack/__init__.py +14 -0
- cancan_microstack/__version__.py +10 -0
- cancan_microstack/assets/__init__.py +6 -0
- cancan_microstack/assets/builds/caddy/Caddyfile +187 -0
- cancan_microstack/assets/builds/caddy/DEPLOYMENT.md +303 -0
- cancan_microstack/assets/builds/caddy/Dockerfile +46 -0
- cancan_microstack/assets/builds/caddy/README.md +343 -0
- cancan_microstack/assets/builds/caddy/geoip/README.md +5 -0
- cancan_microstack/assets/builds/caddy/start.sh +78 -0
- cancan_microstack/assets/builds/caddy/waf/coraza.conf +179 -0
- cancan_microstack/assets/builds/service/Dockerfile +59 -0
- cancan_microstack/assets/builds/service/README.md +13 -0
- cancan_microstack/assets/ddl/create_db.sql +22 -0
- cancan_microstack/assets/ddl/infra/execution_log_tbl.sql +46 -0
- cancan_microstack/assets/ddl/infra/node_instance_tbl.sql +56 -0
- cancan_microstack/assets/ddl/infra/service_action_log_tbl.sql +36 -0
- cancan_microstack/assets/ddl/infra/service_config_tbl.sql +26 -0
- cancan_microstack/assets/ddl/infra/service_info_tbl.sql +45 -0
- cancan_microstack/assets/ddl/infra/service_instance_tbl.sql +54 -0
- cancan_microstack/assets/ddl/infra/service_operation_tbl.sql +47 -0
- cancan_microstack/assets/ddl/infra/workflow_definition_tbl.sql +60 -0
- cancan_microstack/assets/ddl/infra/workflow_definition_version_tbl.sql +35 -0
- cancan_microstack/assets/ddl/infra/workflow_engine_alert_tbl.sql +34 -0
- cancan_microstack/assets/ddl/infra/workflow_run_tbl.sql +52 -0
- cancan_microstack/assets/ddl/ops/admin_user_tbl.sql +34 -0
- cancan_microstack/assets/ddl/ops/caddy_access_log_tbl.sql +91 -0
- cancan_microstack/assets/ddl/ops/caddy_certificate_tbl.sql +59 -0
- cancan_microstack/assets/ddl/ops/caddy_rate_limit_tbl.sql +64 -0
- cancan_microstack/assets/ddl/ops/caddy_route_tbl.sql +63 -0
- cancan_microstack/assets/ddl/ops/caddy_stats_tbl.sql +77 -0
- cancan_microstack/assets/ddl/trigger.sql +21 -0
- cancan_microstack/assets/docker/docker-compose.infra.yml +401 -0
- cancan_microstack/assets/scripts/README.md +195 -0
- cancan_microstack/assets/scripts/docker/build_images.sh +44 -0
- cancan_microstack/assets/scripts/docker/force_rebuild_images.sh +38 -0
- cancan_microstack/assets/scripts/docker/rebuild_all.sh +34 -0
- cancan_microstack/assets/scripts/docker/rebuild_compose.sh +61 -0
- cancan_microstack/assets/scripts/docker/restart.sh +35 -0
- cancan_microstack/assets/scripts/docker/restart_compose.sh +35 -0
- cancan_microstack/assets/scripts/docker/start.sh +78 -0
- cancan_microstack/assets/scripts/docker/start_all.sh +46 -0
- cancan_microstack/assets/scripts/docker/start_compose.sh +66 -0
- cancan_microstack/assets/scripts/docker/stop.sh +67 -0
- cancan_microstack/assets/scripts/docker/stop_all.sh +38 -0
- cancan_microstack/assets/scripts/docker/stop_compose.sh +38 -0
- cancan_microstack/assets/scripts/podman/build_images_podman.sh +59 -0
- cancan_microstack/assets/scripts/podman/cleanup_podman.sh +25 -0
- cancan_microstack/assets/scripts/podman/force_rebuild_images_podman.sh +56 -0
- cancan_microstack/assets/scripts/podman/rebuild_all_podman.sh +37 -0
- cancan_microstack/assets/scripts/podman/rebuild_compose_podman.sh +60 -0
- cancan_microstack/assets/scripts/podman/restart_compose_podman.sh +73 -0
- cancan_microstack/assets/scripts/podman/start_all_podman.sh +66 -0
- cancan_microstack/assets/scripts/podman/start_compose_podman.sh +80 -0
- cancan_microstack/assets/scripts/podman/start_podman.sh +91 -0
- cancan_microstack/assets/scripts/podman/stop.sh +73 -0
- cancan_microstack/assets/scripts/podman/stop_all_podman.sh +34 -0
- cancan_microstack/assets/scripts/podman/stop_compose_podman.sh +58 -0
- cancan_microstack/assets/scripts/start_controllersrv.sh +9 -0
- cancan_microstack/assets/scripts/utils/check_all_db_tables.sh +104 -0
- cancan_microstack/assets/scripts/utils/check_env.sh +177 -0
- cancan_microstack/assets/scripts/utils/check_service_management_deployment.sh +225 -0
- cancan_microstack/assets/scripts/utils/deploy_service_management.sh +176 -0
- cancan_microstack/assets/scripts/utils/force_reload_infrasrv.sh +52 -0
- cancan_microstack/assets/scripts/utils/monitor_service_management.sh +187 -0
- cancan_microstack/assets/scripts/utils/reset_postgres_volume.sh +68 -0
- cancan_microstack/assets/scripts/utils/test_async_operations.sh +141 -0
- cancan_microstack/assets/scripts/utils/verify_real_operations.sh +76 -0
- cancan_microstack/assets/service/Dockerfile +65 -0
- cancan_microstack/assets/www/adminops/assets/AppEmpty.vue_vue_type_script_setup_true_lang-BOKUurnM.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ConfigManage-DKV5YOUz.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ConfigManage-Y5bhy7wG.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ConsoleManage-8ljYvCW2.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ConsoleManage-BWpyqbuQ.css +1 -0
- cancan_microstack/assets/www/adminops/assets/DashboardNew-B9Nf1OPl.js +1 -0
- cancan_microstack/assets/www/adminops/assets/DashboardNew-DYWZKQ1V.css +1 -0
- cancan_microstack/assets/www/adminops/assets/LogSearch-CA0Jhe78.js +1 -0
- cancan_microstack/assets/www/adminops/assets/LogSearch-CCZfTNPF.css +1 -0
- cancan_microstack/assets/www/adminops/assets/LoginView-BId3kP3M.css +1 -0
- cancan_microstack/assets/www/adminops/assets/LoginView-BQZTV_Qy.js +1 -0
- cancan_microstack/assets/www/adminops/assets/OperationProgressDialog-BdEYwqFq.js +1 -0
- cancan_microstack/assets/www/adminops/assets/OperationProgressDialog-D-pASR8G.css +1 -0
- cancan_microstack/assets/www/adminops/assets/PageContainer-Byss-yUC.js +1 -0
- cancan_microstack/assets/www/adminops/assets/PageContainer-C3nSZwM7.css +1 -0
- cancan_microstack/assets/www/adminops/assets/RateLimitManage-BDI8jLpC.css +1 -0
- cancan_microstack/assets/www/adminops/assets/RateLimitManage-DJY4NiF-.js +1 -0
- cancan_microstack/assets/www/adminops/assets/RouteManage-DaUQ4QLw.css +1 -0
- cancan_microstack/assets/www/adminops/assets/RouteManage-w9XCU0UA.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceCard-BFzHe6Tw.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceCard-BJUhWnA-.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceDetail-Cw24WuKp.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceDetail-Yum47zdB.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceList-C7ryvbhE.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceList-Cgd01fUx.css +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceLogs-COpG9H0h.js +1 -0
- cancan_microstack/assets/www/adminops/assets/ServiceLogs-H_Alq0cf.css +1 -0
- cancan_microstack/assets/www/adminops/assets/StatsOverview-D0TwMQkA.js +39 -0
- cancan_microstack/assets/www/adminops/assets/StatsOverview-lqAN6pqM.css +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpBindView-CWlAmzFt.js +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpBindView-HoQC1lhx.css +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpVerifyView-BHN1VtX1.css +1 -0
- cancan_microstack/assets/www/adminops/assets/TotpVerifyView-D3w_lZk8.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowCenter-DU_mpIA0.css +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowCenter-i50rZyxN.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowDesigner-CnHokPL9.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowDesigner-DaZaZpLd.css +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowRuns-B09hK48c.js +1 -0
- cancan_microstack/assets/www/adminops/assets/WorkflowRuns-wGutKIIU.css +1 -0
- cancan_microstack/assets/www/adminops/assets/caddy-nnCKf8fG.js +1 -0
- cancan_microstack/assets/www/adminops/assets/format-Cuzxgna9.js +1 -0
- cancan_microstack/assets/www/adminops/assets/index-CiFlm8oc.js +64 -0
- cancan_microstack/assets/www/adminops/assets/index-UW0T1Dkc.css +1 -0
- cancan_microstack/assets/www/adminops/assets/service-BYlgGPs_.js +1 -0
- cancan_microstack/assets/www/adminops/assets/service-operation-6GzLw2Z1.js +1 -0
- cancan_microstack/assets/www/adminops/assets/style-CcIXnQ5y.css +1 -0
- cancan_microstack/assets/www/adminops/assets/style-lRnStdGu.js +39 -0
- cancan_microstack/assets/www/adminops/assets/useDebounce-BRlqfXqf.js +1 -0
- cancan_microstack/assets/www/adminops/assets/workflow-CUXs39Ac.js +1 -0
- cancan_microstack/assets/www/adminops/index.html +16 -0
- cancan_microstack/assets/www/adminops/vite.svg +1 -0
- cancan_microstack/cli/__init__.py +14 -0
- cancan_microstack/cli/__main__.py +9 -0
- cancan_microstack/cli/main.py +552 -0
- cancan_microstack/cmd/__init__.py +54 -0
- cancan_microstack/cmd/cancan/__init__.py +12 -0
- cancan_microstack/cmd/cancan/run.py +395 -0
- cancan_microstack/cmd/controllersrv/__init__.py +0 -0
- cancan_microstack/cmd/controllersrv/run.py +131 -0
- cancan_microstack/cmd/infrasrv/__init__.py +5 -0
- cancan_microstack/cmd/infrasrv/run.py +100 -0
- cancan_microstack/cmd/opsbffsrv/__init__.py +5 -0
- cancan_microstack/cmd/opsbffsrv/run.py +96 -0
- cancan_microstack/core/__init__.py +5 -0
- cancan_microstack/core/assets.py +123 -0
- cancan_microstack/core/compose_builder.py +102 -0
- cancan_microstack/core/doctor.py +152 -0
- cancan_microstack/core/microstack.py +71 -0
- cancan_microstack/core/runner.py +56 -0
- cancan_microstack/core/stack_manager.py +186 -0
- cancan_microstack/public/__init__.py +7 -0
- cancan_microstack/public/api/__init__.py +1 -0
- cancan_microstack/public/api/controllersrv_client.py +277 -0
- cancan_microstack/public/api/infrasrv_client.py +404 -0
- cancan_microstack/public/const/__init__.py +1 -0
- cancan_microstack/public/const/action_consts.py +18 -0
- cancan_microstack/public/const/app_consts.py +42 -0
- cancan_microstack/public/const/caddy_consts.py +22 -0
- cancan_microstack/public/const/controllersrv_consts.py +163 -0
- cancan_microstack/public/const/docker_consts.py +15 -0
- cancan_microstack/public/const/error.py +56 -0
- cancan_microstack/public/const/health_consts.py +52 -0
- cancan_microstack/public/const/hook_enums.py +56 -0
- cancan_microstack/public/const/logging_enums.py +13 -0
- cancan_microstack/public/const/metrics_enums.py +36 -0
- cancan_microstack/public/const/monitor_enums.py +26 -0
- cancan_microstack/public/const/operation_consts.py +53 -0
- cancan_microstack/public/const/opsbffsrv_error.py +92 -0
- cancan_microstack/public/const/overrides_consts.py +13 -0
- cancan_microstack/public/const/redis.py +17 -0
- cancan_microstack/public/const/service_consts.py +15 -0
- cancan_microstack/public/const/workflow_consts.py +65 -0
- cancan_microstack/public/error.py +41 -0
- cancan_microstack/public/logging/__init__.py +0 -0
- cancan_microstack/public/logging/initializer.py +109 -0
- cancan_microstack/public/logging/mq_handler.py +279 -0
- cancan_microstack/public/schemas/__init__.py +1 -0
- cancan_microstack/public/schemas/caddy/__init__.py +381 -0
- cancan_microstack/public/schemas/caddy/analysis.py +90 -0
- cancan_microstack/public/schemas/caddy/route.py +18 -0
- cancan_microstack/public/schemas/common.py +79 -0
- cancan_microstack/public/schemas/controllersrv/__init__.py +3 -0
- cancan_microstack/public/schemas/controllersrv/async_requests.py +30 -0
- cancan_microstack/public/schemas/controllersrv/compose_models.py +47 -0
- cancan_microstack/public/schemas/controllersrv/const.py +24 -0
- cancan_microstack/public/schemas/controllersrv/docker_models.py +45 -0
- cancan_microstack/public/schemas/controllersrv/docker_responses.py +104 -0
- cancan_microstack/public/schemas/controllersrv/requests.py +54 -0
- cancan_microstack/public/schemas/controllersrv/responses.py +124 -0
- cancan_microstack/public/schemas/controllersrv/task_models.py +102 -0
- cancan_microstack/public/schemas/controllersrv/validation.py +23 -0
- cancan_microstack/public/schemas/hook_metrics.py +124 -0
- cancan_microstack/public/schemas/hooks.py +39 -0
- cancan_microstack/public/schemas/infra/__init__.py +0 -0
- cancan_microstack/public/schemas/infra/cleanup.py +25 -0
- cancan_microstack/public/schemas/infra/container.py +74 -0
- cancan_microstack/public/schemas/infra/enums.py +135 -0
- cancan_microstack/public/schemas/infra/health_check.py +42 -0
- cancan_microstack/public/schemas/infra/hook_log.py +42 -0
- cancan_microstack/public/schemas/infra/operation.py +90 -0
- cancan_microstack/public/schemas/infra/overview.py +25 -0
- cancan_microstack/public/schemas/infra/push.py +33 -0
- cancan_microstack/public/schemas/infra/service_action_log.py +47 -0
- cancan_microstack/public/schemas/infra/service_config.py +10 -0
- cancan_microstack/public/schemas/infra/service_info.py +69 -0
- cancan_microstack/public/schemas/infra/service_instance.py +93 -0
- cancan_microstack/public/schemas/infra/service_management.py +152 -0
- cancan_microstack/public/schemas/infra/service_operation.py +79 -0
- cancan_microstack/public/schemas/infra/service_registry.py +158 -0
- cancan_microstack/public/schemas/infra/status_types.py +19 -0
- cancan_microstack/public/schemas/infra/workflow.py +566 -0
- cancan_microstack/public/schemas/logging/__init__.py +1 -0
- cancan_microstack/public/schemas/logging/log_event.py +121 -0
- cancan_microstack/public/schemas/opsbffsrv/__init__.py +1 -0
- cancan_microstack/public/schemas/opsbffsrv/async_ops.py +17 -0
- cancan_microstack/public/schemas/opsbffsrv/db_admin.py +147 -0
- cancan_microstack/public/schemas/opsbffsrv/db_init.py +48 -0
- cancan_microstack/public/schemas/opsbffsrv/service_config.py +89 -0
- cancan_microstack/public/schemas/opsbffsrv/service_logs.py +54 -0
- cancan_microstack/public/schemas/service_operation.py +24 -0
- cancan_microstack/public/schemas/service_registry.py +40 -0
- cancan_microstack/public/types/__init__.py +7 -0
- cancan_microstack/public/web/__init__.py +0 -0
- cancan_microstack/public/web/config_value.py +105 -0
- cancan_microstack/public/web/server.py +385 -0
- cancan_microstack/py.typed +0 -0
- cancan_microstack/runtime/__init__.py +0 -0
- cancan_microstack/runtime/compose_cmd.py +228 -0
- cancan_microstack/runtime/host_daemon.py +318 -0
- cancan_microstack/runtime/overrides.py +103 -0
- cancan_microstack/runtime/resources.py +25 -0
- cancan_microstack/runtime/workspace.py +94 -0
- cancan_microstack/services/__init__.py +0 -0
- cancan_microstack/services/controllersrv/__init__.py +8 -0
- cancan_microstack/services/controllersrv/application/__init__.py +0 -0
- cancan_microstack/services/controllersrv/application/docker_compose_app.py +427 -0
- cancan_microstack/services/controllersrv/conf/__init__.py +0 -0
- cancan_microstack/services/controllersrv/conf/config.py +76 -0
- cancan_microstack/services/controllersrv/conf/settings.py +54 -0
- cancan_microstack/services/controllersrv/domain/__init__.py +0 -0
- cancan_microstack/services/controllersrv/domain/docker_compose/__init__.py +0 -0
- cancan_microstack/services/controllersrv/domain/docker_compose/docker_compose_domain.py +278 -0
- cancan_microstack/services/controllersrv/domain/service_validator.py +327 -0
- cancan_microstack/services/controllersrv/domain/task/__init__.py +17 -0
- cancan_microstack/services/controllersrv/domain/task/task_queue.py +286 -0
- cancan_microstack/services/controllersrv/domain/task/task_worker.py +495 -0
- cancan_microstack/services/controllersrv/infrastructure/__init__.py +0 -0
- cancan_microstack/services/controllersrv/interface/__init__.py +0 -0
- cancan_microstack/services/controllersrv/interface/api/__init__.py +0 -0
- cancan_microstack/services/controllersrv/interface/api/docker_control_api.py +470 -0
- cancan_microstack/services/controllersrv/router.py +132 -0
- cancan_microstack/services/infrasrv/__init__.py +4 -0
- cancan_microstack/services/infrasrv/application/__init__.py +0 -0
- cancan_microstack/services/infrasrv/application/health_check_app.py +24 -0
- cancan_microstack/services/infrasrv/application/logging/__init__.py +1 -0
- cancan_microstack/services/infrasrv/application/logging/log_ingestion_service.py +183 -0
- cancan_microstack/services/infrasrv/application/service_config.py +22 -0
- cancan_microstack/services/infrasrv/application/service_logs_app.py +53 -0
- cancan_microstack/services/infrasrv/application/service_management_app.py +689 -0
- cancan_microstack/services/infrasrv/application/service_operation_tracker.py +251 -0
- cancan_microstack/services/infrasrv/application/service_registry.py +53 -0
- cancan_microstack/services/infrasrv/application/workflow/__init__.py +0 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_app.py +991 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_queue.py +302 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_tasks.py +46 -0
- cancan_microstack/services/infrasrv/application/workflow/workflow_worker_runtime.py +122 -0
- cancan_microstack/services/infrasrv/conf/__init__.py +0 -0
- cancan_microstack/services/infrasrv/conf/config.py +98 -0
- cancan_microstack/services/infrasrv/domain/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/health_check/__init__.py +3 -0
- cancan_microstack/services/infrasrv/domain/health_check/health_check_domain.py +576 -0
- cancan_microstack/services/infrasrv/domain/hooks/__init__.py +19 -0
- cancan_microstack/services/infrasrv/domain/hooks/builtin_hooks.py +308 -0
- cancan_microstack/services/infrasrv/domain/hooks/hook_registry.py +43 -0
- cancan_microstack/services/infrasrv/domain/hooks/hooks_log_utils.py +275 -0
- cancan_microstack/services/infrasrv/domain/hooks/init.py +17 -0
- cancan_microstack/services/infrasrv/domain/hooks/metrics.py +205 -0
- cancan_microstack/services/infrasrv/domain/hooks/pre_registration_hooks.py +490 -0
- cancan_microstack/services/infrasrv/domain/registry/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/registry/service_registry.py +509 -0
- cancan_microstack/services/infrasrv/domain/service_config/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/service_config/service_config.py +50 -0
- cancan_microstack/services/infrasrv/domain/service_logs/__init__.py +0 -0
- cancan_microstack/services/infrasrv/domain/service_logs/service_logs_domain.py +51 -0
- cancan_microstack/services/infrasrv/domain/workflow/__init__.py +4 -0
- cancan_microstack/services/infrasrv/domain/workflow/engine.py +159 -0
- cancan_microstack/services/infrasrv/domain/workflow/node_handlers.py +509 -0
- cancan_microstack/services/infrasrv/domain/workflow/workflow_domain.py +164 -0
- cancan_microstack/services/infrasrv/infrastructure/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/api/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/api/controllersrv_api.py +165 -0
- cancan_microstack/services/infrasrv/infrastructure/cache/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/cache/service_registry_cache.py +174 -0
- cancan_microstack/services/infrasrv/infrastructure/db/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/execution_log_tbl.py +53 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/node_instance_tbl.py +55 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_action_log_tbl.py +44 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_config_tbl.py +30 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_info_tbl.py +59 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_instance_tbl.py +88 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/service_operation_tbl.py +73 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_definition_tbl.py +55 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_definition_version_tbl.py +43 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_engine_alert_tbl.py +57 -0
- cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_run_tbl.py +56 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/__init__.py +0 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_action_log_op.py +239 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_config.py +80 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_config_manager.py +198 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_info_op.py +297 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_instance_op.py +688 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_operation_op.py +387 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/service_registry.py +124 -0
- cancan_microstack/services/infrasrv/infrastructure/db/operate/workflow_op.py +804 -0
- cancan_microstack/services/infrasrv/infrastructure/ddl_manager.py +31 -0
- cancan_microstack/services/infrasrv/infrastructure/mongo/__init__.py +1 -0
- cancan_microstack/services/infrasrv/infrastructure/mongo/log_repository.py +129 -0
- cancan_microstack/services/infrasrv/interface/__init__.py +0 -0
- cancan_microstack/services/infrasrv/interface/api/__init__.py +0 -0
- cancan_microstack/services/infrasrv/interface/api/health_check_api.py +29 -0
- cancan_microstack/services/infrasrv/interface/api/hooks.py +284 -0
- cancan_microstack/services/infrasrv/interface/api/internal.py +49 -0
- cancan_microstack/services/infrasrv/interface/api/internal_instance_api.py +265 -0
- cancan_microstack/services/infrasrv/interface/api/internal_operation_api.py +206 -0
- cancan_microstack/services/infrasrv/interface/api/service_config.py +50 -0
- cancan_microstack/services/infrasrv/interface/api/service_logs_api.py +49 -0
- cancan_microstack/services/infrasrv/interface/api/service_management_api.py +113 -0
- cancan_microstack/services/infrasrv/interface/api/service_registry.py +117 -0
- cancan_microstack/services/infrasrv/interface/api/workflow_api.py +303 -0
- cancan_microstack/services/infrasrv/interface/schedule/__init__.py +0 -0
- cancan_microstack/services/infrasrv/interface/schedule/cleanup.py +13 -0
- cancan_microstack/services/infrasrv/interface/schedule/health_check.py +27 -0
- cancan_microstack/services/infrasrv/interface/schedule/log_cleanup.py +26 -0
- cancan_microstack/services/infrasrv/interface/schedule/operation_tracker.py +25 -0
- cancan_microstack/services/infrasrv/interface/schedule/scheduler.py +39 -0
- cancan_microstack/services/infrasrv/interface/schedule/workflow_scheduler.py +115 -0
- cancan_microstack/services/infrasrv/router.py +341 -0
- cancan_microstack/services/opsbffsrv/__init__.py +4 -0
- cancan_microstack/services/opsbffsrv/application/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/application/async_operation_app.py +150 -0
- cancan_microstack/services/opsbffsrv/application/auth_app.py +285 -0
- cancan_microstack/services/opsbffsrv/application/caddy/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/application/caddy/access_log_analysis_app.py +344 -0
- cancan_microstack/services/opsbffsrv/application/caddy/access_log_ingestion_service.py +169 -0
- cancan_microstack/services/opsbffsrv/application/caddy/certificate_management_app.py +355 -0
- cancan_microstack/services/opsbffsrv/application/caddy/rate_limit_management_app.py +496 -0
- cancan_microstack/services/opsbffsrv/application/caddy/route_management_app.py +401 -0
- cancan_microstack/services/opsbffsrv/application/caddy/stats_aggregation_app.py +364 -0
- cancan_microstack/services/opsbffsrv/application/db_admin_app.py +103 -0
- cancan_microstack/services/opsbffsrv/application/db_init_app.py +283 -0
- cancan_microstack/services/opsbffsrv/application/logging/__init__.py +1 -0
- cancan_microstack/services/opsbffsrv/application/logging/log_query_app.py +28 -0
- cancan_microstack/services/opsbffsrv/application/service_config.py +158 -0
- cancan_microstack/services/opsbffsrv/application/service_logs_app.py +74 -0
- cancan_microstack/services/opsbffsrv/application/service_registry.py +36 -0
- cancan_microstack/services/opsbffsrv/application/workflow_ops_app.py +730 -0
- cancan_microstack/services/opsbffsrv/conf/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/conf/config.py +224 -0
- cancan_microstack/services/opsbffsrv/domain/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/auth/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/auth/admin_init.py +38 -0
- cancan_microstack/services/opsbffsrv/domain/auth/auth_domain.py +108 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/access_log_analysis.py +358 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/certificate_management.py +325 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/default_routes.py +53 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/rate_limit_management.py +308 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/route_management.py +279 -0
- cancan_microstack/services/opsbffsrv/domain/caddy/stats_aggregation.py +654 -0
- cancan_microstack/services/opsbffsrv/domain/db_admin/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/db_admin/db_admin_domain.py +118 -0
- cancan_microstack/services/opsbffsrv/domain/db_init/__init__.py +3 -0
- cancan_microstack/services/opsbffsrv/domain/db_init/db_init_domain.py +358 -0
- cancan_microstack/services/opsbffsrv/domain/logging/__init__.py +1 -0
- cancan_microstack/services/opsbffsrv/domain/logging/log_query_domain.py +99 -0
- cancan_microstack/services/opsbffsrv/domain/service_config/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/service_config/service_config.py +81 -0
- cancan_microstack/services/opsbffsrv/domain/service_registry/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/domain/service_registry/service_registry.py +292 -0
- cancan_microstack/services/opsbffsrv/infrastructure/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/api/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/api/infrasrv_api.py +242 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/captcha_service.py +67 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/password_service.py +12 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/redis_store.py +131 -0
- cancan_microstack/services/opsbffsrv/infrastructure/auth/totp_service.py +59 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/access_log_parser.py +307 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/admin_api_client.py +678 -0
- cancan_microstack/services/opsbffsrv/infrastructure/caddy/ip_geo_locator.py +176 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/admin_user_tbl.py +33 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_access_log_tbl.py +90 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_certificate_tbl.py +65 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_rate_limit_tbl.py +69 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_route_tbl.py +66 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_stats_tbl.py +78 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_action_log_tbl.py +44 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_config_tbl.py +30 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_info_tbl.py +51 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_instance_tbl.py +68 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/admin_user_operate.py +59 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_access_log.py +531 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_certificate.py +451 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_rate_limit.py +360 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_route.py +271 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_stats.py +343 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_action_log_op.py +57 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_config.py +86 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_info_op.py +79 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_instance.py +58 -0
- cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_registry.py +138 -0
- cancan_microstack/services/opsbffsrv/infrastructure/ddl_manager.py +31 -0
- cancan_microstack/services/opsbffsrv/infrastructure/mongo/__init__.py +1 -0
- cancan_microstack/services/opsbffsrv/infrastructure/mongo/log_query_repository.py +87 -0
- cancan_microstack/services/opsbffsrv/interface/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/interface/api/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/interface/api/async_operation_api.py +137 -0
- cancan_microstack/services/opsbffsrv/interface/api/auth_api.py +113 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/__init__.py +3 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/access_log_api.py +174 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/certificate_api.py +235 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/rate_limit_api.py +302 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/route_api.py +250 -0
- cancan_microstack/services/opsbffsrv/interface/api/caddy/stats_api.py +243 -0
- cancan_microstack/services/opsbffsrv/interface/api/db_admin_api.py +62 -0
- cancan_microstack/services/opsbffsrv/interface/api/db_init_api.py +109 -0
- cancan_microstack/services/opsbffsrv/interface/api/instance_management_api.py +165 -0
- cancan_microstack/services/opsbffsrv/interface/api/log_query_api.py +41 -0
- cancan_microstack/services/opsbffsrv/interface/api/mongo_express_proxy_api.py +181 -0
- cancan_microstack/services/opsbffsrv/interface/api/pgweb_proxy_api.py +154 -0
- cancan_microstack/services/opsbffsrv/interface/api/rabbitmq_mgmt_proxy_api.py +518 -0
- cancan_microstack/services/opsbffsrv/interface/api/redis_commander_proxy_api.py +133 -0
- cancan_microstack/services/opsbffsrv/interface/api/service_config.py +146 -0
- cancan_microstack/services/opsbffsrv/interface/api/service_logs_api.py +81 -0
- cancan_microstack/services/opsbffsrv/interface/api/service_registry.py +66 -0
- cancan_microstack/services/opsbffsrv/interface/api/workflow_ops_api.py +413 -0
- cancan_microstack/services/opsbffsrv/interface/middleware/__init__.py +0 -0
- cancan_microstack/services/opsbffsrv/interface/middleware/auth_middleware.py +52 -0
- cancan_microstack/services/opsbffsrv/router.py +901 -0
- cancan_microstack/utils/__init__.py +1 -0
- cancan_microstack/utils/container_env.py +218 -0
- cancan_microstack-0.0.1.dist-info/METADATA +155 -0
- cancan_microstack-0.0.1.dist-info/RECORD +440 -0
- cancan_microstack-0.0.1.dist-info/WHEEL +5 -0
- cancan_microstack-0.0.1.dist-info/entry_points.txt +2 -0
- cancan_microstack-0.0.1.dist-info/licenses/LICENSE +21 -0
- cancan_microstack-0.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from typing import (
|
|
3
|
+
Any,
|
|
4
|
+
Dict,
|
|
5
|
+
List,
|
|
6
|
+
Optional,
|
|
7
|
+
)
|
|
8
|
+
from datetime import (
|
|
9
|
+
datetime,
|
|
10
|
+
timedelta,
|
|
11
|
+
timezone,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
from linglong_web.utils import logger
|
|
15
|
+
from linglong_web import (
|
|
16
|
+
HTTPClientConfig,
|
|
17
|
+
http_client,
|
|
18
|
+
)
|
|
19
|
+
from linglong_web import LinglongConfig
|
|
20
|
+
from cancan_microstack.public.schemas.infra.service_registry import ServiceRegistryCreate
|
|
21
|
+
from cancan_microstack.public.schemas.infra.service_instance import ServiceInstance
|
|
22
|
+
from cancan_microstack.public.const.health_consts import HealthOverallStatus
|
|
23
|
+
from cancan_microstack.public.const.service_consts import PushStatus
|
|
24
|
+
from cancan_microstack.public.schemas.infra.status_types import InstanceStatus
|
|
25
|
+
from cancan_microstack.public.schemas.infra.push import PushResult, PushDetail
|
|
26
|
+
from cancan_microstack.public.const.action_consts import ActionType
|
|
27
|
+
from cancan_microstack.public.const.operation_consts import OperationStatus, InitiatedBy
|
|
28
|
+
from cancan_microstack.public.schemas.infra.overview import ServiceOverview
|
|
29
|
+
from cancan_microstack.public.schemas.infra.cleanup import CleanupResult, CleanupDetail
|
|
30
|
+
from cancan_microstack.services.infrasrv.infrastructure.db.operate.service_registry import (
|
|
31
|
+
upsert_service_metadata,
|
|
32
|
+
list_service_names,
|
|
33
|
+
)
|
|
34
|
+
from cancan_microstack.services.infrasrv.infrastructure.db.operate.service_config import (
|
|
35
|
+
get_service_config,
|
|
36
|
+
)
|
|
37
|
+
from cancan_microstack.services.infrasrv.infrastructure.db.operate.service_action_log_op import (
|
|
38
|
+
insert_service_action_log,
|
|
39
|
+
)
|
|
40
|
+
from cancan_microstack.services.infrasrv.infrastructure.db.operate.service_instance_op import (
|
|
41
|
+
get_instance_by_id,
|
|
42
|
+
list_instances_by_service,
|
|
43
|
+
get_all_instances as list_all_instances,
|
|
44
|
+
upsert_instance,
|
|
45
|
+
soft_delete_instance,
|
|
46
|
+
mark_instance_status,
|
|
47
|
+
hard_delete_instances_by_ids,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
class ServiceRegistry:
|
|
52
|
+
"""服务注册发现域"""
|
|
53
|
+
|
|
54
|
+
_INVALID_HOSTS = {"unknown", "localhost", "127.0.0.1", "0.0.0.0"}
|
|
55
|
+
_CONTAINER_ID_PATTERN = re.compile(r"^(?:[0-9a-f]{12}|[0-9a-f]{64})$", re.IGNORECASE)
|
|
56
|
+
|
|
57
|
+
# 健康检查配置常量
|
|
58
|
+
# Note: use HealthCheckDomain for multi-instance checks
|
|
59
|
+
|
|
60
|
+
async def register(self, service: ServiceRegistryCreate) -> None:
|
|
61
|
+
"""
|
|
62
|
+
注册服务实例
|
|
63
|
+
|
|
64
|
+
验证规则:
|
|
65
|
+
1. host 不能为 unknown(通常是 Docker 容器hostname 未正确设置)
|
|
66
|
+
2. host 不能为空或纯空格
|
|
67
|
+
3. 拒绝明显无效的服务名(infrasrv 等特殊服务)
|
|
68
|
+
"""
|
|
69
|
+
normalized_host = self._normalize_instance_host(service)
|
|
70
|
+
|
|
71
|
+
# 验证服务名
|
|
72
|
+
if service.service_name in ("infrasrv", "controllersrv"):
|
|
73
|
+
logger.warning(f"Reject registration: special service '{service.service_name}' should not register itself")
|
|
74
|
+
raise ValueError(f"Special service '{service.service_name}' should not register")
|
|
75
|
+
|
|
76
|
+
logger.info(
|
|
77
|
+
"Registering service metadata and instance: %s (%s) @ %s",
|
|
78
|
+
service.service_name,
|
|
79
|
+
service.instance_id,
|
|
80
|
+
normalized_host,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
await upsert_service_metadata(service.to_service_metadata())
|
|
84
|
+
await upsert_instance(self._build_instance_payload(service, normalized_host))
|
|
85
|
+
|
|
86
|
+
@staticmethod
|
|
87
|
+
def _is_local_dev_instance(service: ServiceRegistryCreate) -> bool:
|
|
88
|
+
"""
|
|
89
|
+
判断实例是否来自容器外本地环境
|
|
90
|
+
Determine whether the instance originates from out-of-pod local dev.
|
|
91
|
+
"""
|
|
92
|
+
service_meta = service.service_metadata or {}
|
|
93
|
+
instance_meta = service.instance_metadata or {}
|
|
94
|
+
return bool(service_meta.get("is_local_dev") or instance_meta.get("is_local_dev"))
|
|
95
|
+
|
|
96
|
+
@classmethod
|
|
97
|
+
def _looks_like_container_hostname(cls, host: str) -> bool:
|
|
98
|
+
"""
|
|
99
|
+
检测 host 是否为容器 ID
|
|
100
|
+
Detect whether the host string is a container identifier.
|
|
101
|
+
"""
|
|
102
|
+
return bool(cls._CONTAINER_ID_PATTERN.fullmatch(host.strip()))
|
|
103
|
+
|
|
104
|
+
@staticmethod
|
|
105
|
+
def _fallback_host_alias(service: ServiceRegistryCreate) -> Optional[str]:
|
|
106
|
+
"""
|
|
107
|
+
生成可回退的网络别名(优先使用 compose/metadata 提供的值)
|
|
108
|
+
Build the fallback alias (compose alias > metadata > service name).
|
|
109
|
+
"""
|
|
110
|
+
instance_meta = service.instance_metadata or {}
|
|
111
|
+
candidates = [
|
|
112
|
+
instance_meta.get("network_alias"),
|
|
113
|
+
service.compose_service_name,
|
|
114
|
+
f"{service.service_name}.service",
|
|
115
|
+
]
|
|
116
|
+
for candidate in candidates:
|
|
117
|
+
if candidate:
|
|
118
|
+
return candidate
|
|
119
|
+
return None
|
|
120
|
+
|
|
121
|
+
def _normalize_instance_host(self, service: ServiceRegistryCreate) -> str:
|
|
122
|
+
"""
|
|
123
|
+
归一化实例 host,确保 infrasrv 可以回连
|
|
124
|
+
Normalize the instance host so infrasrv can reach the service.
|
|
125
|
+
"""
|
|
126
|
+
raw_host = (service.host or "").strip()
|
|
127
|
+
is_local_dev = self._is_local_dev_instance(service)
|
|
128
|
+
|
|
129
|
+
if not raw_host:
|
|
130
|
+
fallback = self._fallback_host_alias(service)
|
|
131
|
+
if fallback:
|
|
132
|
+
logger.warning(
|
|
133
|
+
"Host missing for %s:%s, falling back to alias '%s'",
|
|
134
|
+
service.service_name,
|
|
135
|
+
service.instance_id,
|
|
136
|
+
fallback,
|
|
137
|
+
)
|
|
138
|
+
return fallback
|
|
139
|
+
raise ValueError("Invalid host: host cannot be empty")
|
|
140
|
+
|
|
141
|
+
lowered = raw_host.lower()
|
|
142
|
+
if lowered in self._INVALID_HOSTS:
|
|
143
|
+
if lowered == "127.0.0.1" and is_local_dev:
|
|
144
|
+
return raw_host
|
|
145
|
+
fallback = self._fallback_host_alias(service)
|
|
146
|
+
if fallback:
|
|
147
|
+
logger.info(
|
|
148
|
+
"Replacing invalid host '%s' with alias '%s' for %s:%s",
|
|
149
|
+
raw_host,
|
|
150
|
+
fallback,
|
|
151
|
+
service.service_name,
|
|
152
|
+
service.instance_id,
|
|
153
|
+
)
|
|
154
|
+
return fallback
|
|
155
|
+
raise ValueError(
|
|
156
|
+
f"Invalid host: '{raw_host}' is not routable. Configure SERVICE_NETWORK_ALIAS or hostname."
|
|
157
|
+
)
|
|
158
|
+
|
|
159
|
+
if self._looks_like_container_hostname(raw_host):
|
|
160
|
+
fallback = self._fallback_host_alias(service)
|
|
161
|
+
if fallback:
|
|
162
|
+
logger.info(
|
|
163
|
+
"Replacing container hostname '%s' with alias '%s' for %s:%s",
|
|
164
|
+
raw_host,
|
|
165
|
+
fallback,
|
|
166
|
+
service.service_name,
|
|
167
|
+
service.instance_id,
|
|
168
|
+
)
|
|
169
|
+
return fallback
|
|
170
|
+
logger.warning(
|
|
171
|
+
"Host '%s' looks like a container ID but no alias found for %s:%s",
|
|
172
|
+
raw_host,
|
|
173
|
+
service.service_name,
|
|
174
|
+
service.instance_id,
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
return raw_host
|
|
178
|
+
|
|
179
|
+
def _build_instance_payload(self, service: ServiceRegistryCreate, normalized_host: str):
|
|
180
|
+
"""
|
|
181
|
+
构造用于 upsert 的实例载荷,同时保存原始 host 信息
|
|
182
|
+
Build the instance payload for persistence and keep host provenance.
|
|
183
|
+
"""
|
|
184
|
+
payload = service.to_instance_payload()
|
|
185
|
+
metadata = dict(payload.instance_metadata or {})
|
|
186
|
+
metadata.setdefault("resolved_host", normalized_host)
|
|
187
|
+
if service.host != normalized_host:
|
|
188
|
+
metadata["reported_host"] = service.host
|
|
189
|
+
return payload.model_copy(update={
|
|
190
|
+
"host": normalized_host,
|
|
191
|
+
"instance_metadata": metadata,
|
|
192
|
+
})
|
|
193
|
+
|
|
194
|
+
async def deregister(self, service_name: str, instance_id: str) -> None:
|
|
195
|
+
"""注销服务实例"""
|
|
196
|
+
logger.info(f"Deregistering service: {service_name}, instance: {instance_id}")
|
|
197
|
+
await mark_instance_status(service_name, instance_id, InstanceStatus.DOWN)
|
|
198
|
+
await soft_delete_instance(service_name, instance_id)
|
|
199
|
+
|
|
200
|
+
async def get_instances(self, service_name: str, only_healthy: bool = True) -> List[ServiceInstance]:
|
|
201
|
+
"""获取服务实例列表"""
|
|
202
|
+
instances = await list_instances_by_service(service_name)
|
|
203
|
+
if only_healthy:
|
|
204
|
+
return [inst for inst in instances if inst.status == InstanceStatus.UP]
|
|
205
|
+
return instances
|
|
206
|
+
|
|
207
|
+
async def get_all_instances(self) -> List[ServiceInstance]:
|
|
208
|
+
"""获取所有服务实例"""
|
|
209
|
+
return await list_all_instances()
|
|
210
|
+
|
|
211
|
+
async def get_instance(self, service_name: str, instance_id: str) -> Optional[ServiceInstance]:
|
|
212
|
+
"""获取指定服务实例"""
|
|
213
|
+
instance = await get_instance_by_id(instance_id)
|
|
214
|
+
if instance and instance.service_name != service_name:
|
|
215
|
+
return None
|
|
216
|
+
return instance
|
|
217
|
+
|
|
218
|
+
async def push_config_to_service(self, service_name: str) -> Dict[str, Any]:
|
|
219
|
+
"""向服务推送配置"""
|
|
220
|
+
logger.info(f"Pushing config to service: {service_name}")
|
|
221
|
+
|
|
222
|
+
# 获取服务配置
|
|
223
|
+
config_dict = {}
|
|
224
|
+
configs = await get_service_config(service_name)
|
|
225
|
+
if configs:
|
|
226
|
+
config_dict = {c.conf_key: c.conf_value for c in configs}
|
|
227
|
+
|
|
228
|
+
# 获取健康的服务实例
|
|
229
|
+
instances = await list_instances_by_service(service_name)
|
|
230
|
+
instances = [inst for inst in instances if inst.status == InstanceStatus.UP]
|
|
231
|
+
|
|
232
|
+
push_results = PushResult(service_name=service_name, total_instances=len(instances))
|
|
233
|
+
|
|
234
|
+
for instance in instances:
|
|
235
|
+
try:
|
|
236
|
+
# 确定推送配置使用的host
|
|
237
|
+
is_local_dev = False
|
|
238
|
+
if instance.instance_metadata:
|
|
239
|
+
is_local_dev = instance.instance_metadata.get("is_local_dev", False)
|
|
240
|
+
|
|
241
|
+
push_host = "127.0.0.1" if is_local_dev else instance.host
|
|
242
|
+
|
|
243
|
+
url = f"http://{push_host}:{instance.port}/internal/config/update"
|
|
244
|
+
|
|
245
|
+
resp = await http_client.post(url, json={"config": config_dict},
|
|
246
|
+
timeout=HTTPClientConfig.INTERNAL_SERVICE_TIMEOUT)
|
|
247
|
+
|
|
248
|
+
if resp and resp.status == 200:
|
|
249
|
+
push_results.success += 1
|
|
250
|
+
push_results.details.append(
|
|
251
|
+
PushDetail(
|
|
252
|
+
instance_id=instance.instance_id,
|
|
253
|
+
host=instance.host,
|
|
254
|
+
port=instance.port,
|
|
255
|
+
status=PushStatus.SUCCESS,
|
|
256
|
+
)
|
|
257
|
+
)
|
|
258
|
+
else:
|
|
259
|
+
push_results.failed += 1
|
|
260
|
+
push_results.details.append(
|
|
261
|
+
PushDetail(
|
|
262
|
+
instance_id=instance.instance_id,
|
|
263
|
+
host=instance.host,
|
|
264
|
+
port=instance.port,
|
|
265
|
+
status=PushStatus.FAILED,
|
|
266
|
+
error=f"HTTP {resp.status if resp else 'None'}",
|
|
267
|
+
)
|
|
268
|
+
)
|
|
269
|
+
# 推送配置失败,增加失败计数(不立即标记为DOWN)
|
|
270
|
+
logger.warning(
|
|
271
|
+
f"Failed to push config to {instance.service_name}:{instance.instance_id}, "
|
|
272
|
+
f"will be caught in next health check"
|
|
273
|
+
)
|
|
274
|
+
except Exception as e:
|
|
275
|
+
push_results.failed += 1
|
|
276
|
+
push_results.details.append(
|
|
277
|
+
PushDetail(
|
|
278
|
+
instance_id=instance.instance_id,
|
|
279
|
+
host=instance.host,
|
|
280
|
+
port=instance.port,
|
|
281
|
+
status=PushStatus.FAILED,
|
|
282
|
+
error=str(e),
|
|
283
|
+
)
|
|
284
|
+
)
|
|
285
|
+
logger.error(f"Failed to push config to {instance.instance_id}: {e}")
|
|
286
|
+
|
|
287
|
+
logger.info(f"Config push completed: {push_results.success} success, {push_results.failed} failed")
|
|
288
|
+
return push_results.model_dump()
|
|
289
|
+
|
|
290
|
+
async def get_all_service_names(self) -> List[str]:
|
|
291
|
+
return await list_service_names()
|
|
292
|
+
|
|
293
|
+
async def get_services_overview(self) -> List[Dict[str, Any]]:
|
|
294
|
+
"""获取所有服务的概览信息(服务名、状态统计)"""
|
|
295
|
+
all_instances = await list_all_instances()
|
|
296
|
+
|
|
297
|
+
# 使用结构化模型返回服务概览
|
|
298
|
+
overview_map: Dict[str, ServiceOverview] = {}
|
|
299
|
+
|
|
300
|
+
for instance in all_instances:
|
|
301
|
+
service_name = instance.service_name
|
|
302
|
+
if service_name not in overview_map:
|
|
303
|
+
overview_map[service_name] = ServiceOverview(
|
|
304
|
+
service_name=service_name,
|
|
305
|
+
total_instances=0,
|
|
306
|
+
healthy_instances=0,
|
|
307
|
+
unhealthy_instances=0,
|
|
308
|
+
overall_status=HealthOverallStatus.UP,
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
ov = overview_map[service_name]
|
|
312
|
+
ov.total_instances += 1
|
|
313
|
+
# 尝试将实例状态转换为枚举以便比较,如果失败则回退为原始字符串
|
|
314
|
+
try:
|
|
315
|
+
inst_status = InstanceStatus(instance.status)
|
|
316
|
+
except Exception:
|
|
317
|
+
inst_status = instance.status
|
|
318
|
+
|
|
319
|
+
if inst_status == InstanceStatus.UP:
|
|
320
|
+
ov.healthy_instances += 1
|
|
321
|
+
else:
|
|
322
|
+
ov.unhealthy_instances += 1
|
|
323
|
+
|
|
324
|
+
# 计算整体状态
|
|
325
|
+
for service_name, ov in overview_map.items():
|
|
326
|
+
if ov.healthy_instances == 0:
|
|
327
|
+
ov.overall_status = HealthOverallStatus.DOWN
|
|
328
|
+
elif ov.unhealthy_instances > 0:
|
|
329
|
+
ov.overall_status = HealthOverallStatus.PARTIAL
|
|
330
|
+
else:
|
|
331
|
+
ov.overall_status = HealthOverallStatus.UP
|
|
332
|
+
|
|
333
|
+
return [ov.model_dump() for ov in overview_map.values()]
|
|
334
|
+
|
|
335
|
+
async def cleanup_dead_instances(self) -> Dict[str, Any]:
|
|
336
|
+
"""
|
|
337
|
+
清理僵尸和已下线的服务实例
|
|
338
|
+
Cleanup zombie and downed service instances.
|
|
339
|
+
|
|
340
|
+
执行两个阶段的清理:
|
|
341
|
+
1. **标记僵尸实例**:将心跳超时的 `UP` 状态实例标记为 `DOWN` (软删除)。
|
|
342
|
+
2. **清理下线实例**:物理删除状态为 `DOWN` 且超过清理周期的实例。
|
|
343
|
+
"""
|
|
344
|
+
logger.info("Starting cleanup/health-check of service instances...")
|
|
345
|
+
all_instances = await list_all_instances()
|
|
346
|
+
|
|
347
|
+
timeout_seconds = LinglongConfig.INSTANCE_HEARTBEAT_TIMEOUT_SECONDS
|
|
348
|
+
cleanup_threshold = timedelta(seconds=timeout_seconds)
|
|
349
|
+
current_time = datetime.now(timezone.utc)
|
|
350
|
+
|
|
351
|
+
instances_to_soft_delete = []
|
|
352
|
+
instances_to_hard_delete = []
|
|
353
|
+
kept_count = 0
|
|
354
|
+
|
|
355
|
+
for instance in all_instances:
|
|
356
|
+
# --- 阶段1: 识别僵尸实例 ---
|
|
357
|
+
if instance.status == InstanceStatus.UP:
|
|
358
|
+
is_stale = False
|
|
359
|
+
last_heartbeat = instance.last_heartbeat
|
|
360
|
+
if last_heartbeat:
|
|
361
|
+
if last_heartbeat.tzinfo is None:
|
|
362
|
+
last_heartbeat = last_heartbeat.replace(tzinfo=timezone.utc)
|
|
363
|
+
if (current_time - last_heartbeat) > cleanup_threshold:
|
|
364
|
+
is_stale = True
|
|
365
|
+
else:
|
|
366
|
+
created_time = instance.created_time
|
|
367
|
+
if created_time:
|
|
368
|
+
if created_time.tzinfo is None:
|
|
369
|
+
created_time = created_time.replace(tzinfo=timezone.utc)
|
|
370
|
+
if (current_time - created_time) > cleanup_threshold:
|
|
371
|
+
is_stale = True
|
|
372
|
+
|
|
373
|
+
if is_stale:
|
|
374
|
+
instances_to_soft_delete.append(instance)
|
|
375
|
+
else:
|
|
376
|
+
kept_count += 1
|
|
377
|
+
|
|
378
|
+
# --- 阶段2: 识别需要物理删除的实例 ---
|
|
379
|
+
elif instance.status == InstanceStatus.DOWN:
|
|
380
|
+
update_time = instance.update_time
|
|
381
|
+
if update_time:
|
|
382
|
+
if update_time.tzinfo is None:
|
|
383
|
+
update_time = update_time.replace(tzinfo=timezone.utc)
|
|
384
|
+
if (current_time - update_time) > cleanup_threshold:
|
|
385
|
+
instances_to_hard_delete.append(instance)
|
|
386
|
+
else:
|
|
387
|
+
kept_count += 1
|
|
388
|
+
else:
|
|
389
|
+
# 如果没有更新时间,默认保留
|
|
390
|
+
kept_count += 1
|
|
391
|
+
else:
|
|
392
|
+
kept_count += 1
|
|
393
|
+
|
|
394
|
+
# --- 执行数据库操作 ---
|
|
395
|
+
cleanup_results = CleanupResult(
|
|
396
|
+
total_checked=len(all_instances),
|
|
397
|
+
kept=kept_count
|
|
398
|
+
)
|
|
399
|
+
|
|
400
|
+
# 执行软删除
|
|
401
|
+
for instance in instances_to_soft_delete:
|
|
402
|
+
try:
|
|
403
|
+
await soft_delete_instance(instance.service_name, instance.instance_id)
|
|
404
|
+
cleanup_results.cleaned += 1
|
|
405
|
+
cleanup_results.details.append(CleanupDetail(
|
|
406
|
+
service_name=instance.service_name,
|
|
407
|
+
instance_id=instance.instance_id,
|
|
408
|
+
action="soft_deleted",
|
|
409
|
+
reason="Stale heartbeat",
|
|
410
|
+
))
|
|
411
|
+
logger.info(f"Soft deleted stale instance: {instance.service_name}:{instance.instance_id}")
|
|
412
|
+
except Exception as e:
|
|
413
|
+
logger.error(f"Failed to soft-delete instance {instance.instance_id}: {e}")
|
|
414
|
+
|
|
415
|
+
# 执行物理删除
|
|
416
|
+
if instances_to_hard_delete:
|
|
417
|
+
instance_ids_to_delete = [inst.instance_id for inst in instances_to_hard_delete]
|
|
418
|
+
try:
|
|
419
|
+
deleted_count = await hard_delete_instances_by_ids(instance_ids_to_delete)
|
|
420
|
+
cleanup_results.cleaned += deleted_count
|
|
421
|
+
for inst in instances_to_hard_delete:
|
|
422
|
+
cleanup_results.details.append(CleanupDetail(
|
|
423
|
+
service_name=inst.service_name,
|
|
424
|
+
instance_id=inst.instance_id,
|
|
425
|
+
action="hard_deleted",
|
|
426
|
+
reason="Downed instance expired",
|
|
427
|
+
))
|
|
428
|
+
logger.info(f"Hard deleted {deleted_count} expired downed instances.")
|
|
429
|
+
except Exception as e:
|
|
430
|
+
logger.error(f"Failed to hard-delete instances: {e}")
|
|
431
|
+
|
|
432
|
+
logger.info(
|
|
433
|
+
f"Health check completed: {cleanup_results.cleaned} instances cleaned, "
|
|
434
|
+
f"{cleanup_results.kept} instances kept."
|
|
435
|
+
)
|
|
436
|
+
return cleanup_results.model_dump()
|
|
437
|
+
|
|
438
|
+
async def _auto_restart_service(self, service_name: str, instance_id: str):
|
|
439
|
+
"""
|
|
440
|
+
自动重启失败的服务
|
|
441
|
+
|
|
442
|
+
Args:
|
|
443
|
+
service_name: 服务名称
|
|
444
|
+
instance_id: 实例ID
|
|
445
|
+
"""
|
|
446
|
+
try:
|
|
447
|
+
# 记录日志:准备重启
|
|
448
|
+
logger.info(f"Auto-restarting service {service_name}:{instance_id} via controllersrv")
|
|
449
|
+
|
|
450
|
+
# 记录行为日志
|
|
451
|
+
await insert_service_action_log(
|
|
452
|
+
service_name=service_name,
|
|
453
|
+
action_type=ActionType.AUTO_RESTART,
|
|
454
|
+
action_status=OperationStatus.PENDING,
|
|
455
|
+
triggered_by=InitiatedBy.INFRASRV,
|
|
456
|
+
action_metadata={"instance_id": instance_id, "reason": "health_check_failure"}
|
|
457
|
+
)
|
|
458
|
+
|
|
459
|
+
# 调用 controllersrv 重启服务
|
|
460
|
+
controllersrv_url = f"{LinglongConfig.CONTROLLERSRV_HOST}/v1/controllersrv/service/restart"
|
|
461
|
+
resp = await http_client.post(
|
|
462
|
+
url=controllersrv_url,
|
|
463
|
+
json={"service_names": [service_name]},
|
|
464
|
+
timeout=HTTPClientConfig.INTERNAL_SERVICE_TIMEOUT
|
|
465
|
+
)
|
|
466
|
+
|
|
467
|
+
if resp and resp.status == 200:
|
|
468
|
+
data = await resp.json()
|
|
469
|
+
if data.get("success"):
|
|
470
|
+
logger.info(f"Successfully triggered restart for service {service_name}")
|
|
471
|
+
await insert_service_action_log(
|
|
472
|
+
service_name=service_name,
|
|
473
|
+
action_type=ActionType.AUTO_RESTART,
|
|
474
|
+
action_status=OperationStatus.SUCCESS,
|
|
475
|
+
triggered_by=InitiatedBy.INFRASRV,
|
|
476
|
+
action_metadata={"instance_id": instance_id, "controllersrv_response": data}
|
|
477
|
+
)
|
|
478
|
+
else:
|
|
479
|
+
error_msg = data.get("error", {}).get("msg", "Unknown error")
|
|
480
|
+
logger.error(f"Failed to restart service {service_name}: {error_msg}")
|
|
481
|
+
await insert_service_action_log(
|
|
482
|
+
service_name=service_name,
|
|
483
|
+
action_type=ActionType.AUTO_RESTART,
|
|
484
|
+
action_status=OperationStatus.FAILED,
|
|
485
|
+
triggered_by=InitiatedBy.INFRASRV,
|
|
486
|
+
error_message=error_msg,
|
|
487
|
+
action_metadata={"instance_id": instance_id}
|
|
488
|
+
)
|
|
489
|
+
else:
|
|
490
|
+
error_msg = f"HTTP error: {resp.status if resp else 'no response'}"
|
|
491
|
+
logger.error(f"Failed to call controllersrv for {service_name}: {error_msg}")
|
|
492
|
+
await insert_service_action_log(
|
|
493
|
+
service_name=service_name,
|
|
494
|
+
action_type=ActionType.AUTO_RESTART,
|
|
495
|
+
action_status=OperationStatus.FAILED,
|
|
496
|
+
triggered_by=InitiatedBy.INFRASRV,
|
|
497
|
+
error_message=error_msg,
|
|
498
|
+
action_metadata={"instance_id": instance_id}
|
|
499
|
+
)
|
|
500
|
+
except Exception as e:
|
|
501
|
+
logger.error(f"Error auto-restarting service {service_name}: {e}", exc_info=True)
|
|
502
|
+
await insert_service_action_log(
|
|
503
|
+
service_name=service_name,
|
|
504
|
+
action_type=ActionType.AUTO_RESTART,
|
|
505
|
+
action_status=OperationStatus.FAILED,
|
|
506
|
+
triggered_by=InitiatedBy.INFRASRV,
|
|
507
|
+
error_message=str(e),
|
|
508
|
+
action_metadata={"instance_id": instance_id}
|
|
509
|
+
)
|
|
File without changes
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
from cancan_microstack.services.infrasrv.infrastructure.db.operate.service_config import (
|
|
2
|
+
insert_service_config,
|
|
3
|
+
get_service_config,
|
|
4
|
+
update_service_config,
|
|
5
|
+
get_all_service_configs as db_get_all_service_configs,
|
|
6
|
+
delete_service_config as db_delete_service_config,
|
|
7
|
+
)
|
|
8
|
+
from cancan_microstack.public.schemas.infra.service_config import ServiceConfig as ServiceConfigSchema
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ServiceConfig:
|
|
12
|
+
|
|
13
|
+
async def get_service_config(self, service_name: str) -> dict:
|
|
14
|
+
confs = await get_service_config(service_name)
|
|
15
|
+
if not confs:
|
|
16
|
+
return {}
|
|
17
|
+
return {c.conf_key: c.conf_value for c in confs}
|
|
18
|
+
|
|
19
|
+
async def insert_service_config(self, service_name: str, conf_dict: dict) -> None:
|
|
20
|
+
confs = [ServiceConfigSchema(
|
|
21
|
+
service_name=service_name,
|
|
22
|
+
conf_key=k,
|
|
23
|
+
conf_value=v
|
|
24
|
+
) for k, v in conf_dict.items()]
|
|
25
|
+
await insert_service_config(confs)
|
|
26
|
+
|
|
27
|
+
async def update_service_config(self, service_name: str, conf_dict: dict) -> None:
|
|
28
|
+
confs = [ServiceConfigSchema(
|
|
29
|
+
service_name=service_name,
|
|
30
|
+
conf_key=k,
|
|
31
|
+
conf_value=v
|
|
32
|
+
) for k, v in conf_dict.items()]
|
|
33
|
+
await update_service_config(confs)
|
|
34
|
+
|
|
35
|
+
async def get_all_service_configs(self) -> dict:
|
|
36
|
+
"""获取所有服务的配置"""
|
|
37
|
+
all_confs = await db_get_all_service_configs()
|
|
38
|
+
|
|
39
|
+
# 按服务名分组
|
|
40
|
+
result = {}
|
|
41
|
+
for conf in all_confs:
|
|
42
|
+
if conf.service_name not in result:
|
|
43
|
+
result[conf.service_name] = {}
|
|
44
|
+
result[conf.service_name][conf.conf_key] = conf.conf_value
|
|
45
|
+
|
|
46
|
+
return result
|
|
47
|
+
|
|
48
|
+
async def delete_service_config(self, service_name: str, conf_key: str) -> None:
|
|
49
|
+
"""删除服务配置项"""
|
|
50
|
+
await db_delete_service_config(service_name, conf_key)
|
|
File without changes
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"""
|
|
2
|
+
服务行为日志领域层
|
|
3
|
+
"""
|
|
4
|
+
from typing import (
|
|
5
|
+
List,
|
|
6
|
+
Optional,
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
from linglong_web.utils import logger
|
|
10
|
+
from cancan_microstack.public.schemas.infra.service_action_log import ServiceActionLog
|
|
11
|
+
from cancan_microstack.services.infrasrv.infrastructure.db.operate.service_action_log_op import (
|
|
12
|
+
query_service_action_logs,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ServiceLogsDomain:
|
|
17
|
+
"""服务日志领域层:处理日志查询业务逻辑"""
|
|
18
|
+
|
|
19
|
+
async def get_service_action_logs(
|
|
20
|
+
self,
|
|
21
|
+
service_name: Optional[str] = None,
|
|
22
|
+
action_type: Optional[str] = None,
|
|
23
|
+
action_status: Optional[str] = None,
|
|
24
|
+
limit: int = 100
|
|
25
|
+
) -> List[ServiceActionLog]:
|
|
26
|
+
"""
|
|
27
|
+
查询服务行为日志
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
service_name: 服务名称(可选)
|
|
31
|
+
action_type: 操作类型(可选)
|
|
32
|
+
action_status: 操作状态(可选)
|
|
33
|
+
limit: 返回数量限制
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
服务行为日志列表
|
|
37
|
+
"""
|
|
38
|
+
logger.info(
|
|
39
|
+
f"ServiceLogsDomain: querying logs - service_name={service_name}, "
|
|
40
|
+
f"action_type={action_type}, action_status={action_status}, limit={limit}"
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# 调用基础设施层查询数据
|
|
44
|
+
logs = await query_service_action_logs(
|
|
45
|
+
service_name=service_name,
|
|
46
|
+
action_type=action_type,
|
|
47
|
+
action_status=action_status,
|
|
48
|
+
limit=limit
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
return logs
|