feat(server): 支持 MySQL 一主多从拓扑调度与复制健康检查

- DeliveryTask/DeploymentResult 新增 target_hosts/target_host_ips 完整节点列表(主节点在前)
- 交付输入支持 replica_count(1-7)与有序 target_hosts,按节点数放大配额/预留/资源用量
- 端口占用与已占主机解析改为逗号列表,兼容存量单主机字段
- 指定主机校验池成员/重复/单机实例数,自动补齐剩余节点或延后调度
- AWX Limit 与回滚覆盖全部节点,extra_vars 下发主从主机与 IP 列表
- completeTask 全节点 TCP 探活,副本经 mysqlReplicationReady 校验复制线程状态
- awxTaskSummary 按服务类型生成摘要;go-sql-driver/mysql 提为直接依赖
This commit is contained in:
Hungerdream
2026-07-31 18:12:05 +08:00
parent 242326ccc5
commit 0ca3af39dc
6 changed files with 392 additions and 46 deletions
+9 -2
View File
@@ -216,11 +216,18 @@ func (h *TaskLogHandler) getWayneTask(c *gin.Context, id string, userID uint64,
}
func awxTaskSummary(task model.DeliveryTask) taskLogSummary {
serviceName := "mysql"
serviceLabel := "MySQL"
if strings.EqualFold(strings.TrimSpace(task.ServiceType), "postgresql") ||
(strings.TrimSpace(task.ServiceType) == "" && strings.EqualFold(strings.TrimSpace(task.Component), "postgresql")) {
serviceName = "postgresql"
serviceLabel = "PostgreSQL"
}
return taskLogSummary{
ID: "awx:" + task.ID,
Source: "awx",
Service: "mysql",
Name: "MySQL 标准化交付 · " + task.InstanceName,
Service: serviceName,
Name: serviceLabel + " 标准化交付 · " + task.InstanceName,
Runner: "AWX Job Template #" + strconv.FormatUint(task.TargetID, 10),
Status: task.Status,
StatusText: textForTaskStatus(task.Status),
+27
View File
@@ -439,6 +439,33 @@ func TestAwxTaskSummary(t *testing.T) {
}
}
func TestAwxTaskSummaryPostgreSQL(t *testing.T) {
tests := []struct {
name string
serviceType string
component string
}{
{name: "service type", serviceType: "postgresql", component: "postgresql"},
{name: "legacy component fallback", component: "postgresql"},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
summary := awxTaskSummary(model.DeliveryTask{
ID: "task-postgresql",
ServiceType: tt.serviceType,
Component: tt.component,
InstanceName: "postgresql-xinfra-n1aw28",
})
if summary.Service != "postgresql" {
t.Fatalf("awxTaskSummary Service = %q, want %q", summary.Service, "postgresql")
}
if summary.Name != "PostgreSQL 标准化交付 · postgresql-xinfra-n1aw28" {
t.Fatalf("awxTaskSummary Name = %q, want PostgreSQL delivery name", summary.Name)
}
})
}
}
func TestWayneTaskSummary(t *testing.T) {
now := time.Now()
history := service.WayneDeploymentHistory{