feat: switch base delivery to awx task logs

This commit is contained in:
mac
2026-07-23 18:36:24 +08:00
parent c2a3bbbdc0
commit a934380c9c
20 changed files with 1638 additions and 1243 deletions
+124
View File
@@ -0,0 +1,124 @@
import { getToken } from '@/utils/auth'
export interface DeliveryTarget {
id: number
name: string
target_type: string
awx_inventory_id: number
awx_template_id: number
enabled: boolean
metadata?: string
}
export interface CreateMySQLDeliveryPayload {
business_line_id: number
target_id: number
namespace: string
instance_name: string
mysql_version: string
cpu_milli: number
memory_mi: number
storage_gi: number
}
export interface DeliveryTask {
id: string
business_line_id: number
requested_by: number
target_type: string
target_id: number
namespace: string
instance_name: string
target_host?: string
target_host_ip?: string
mysql_port?: number
status: string
error_message?: string
created_at: string
updated_at: string
started_at?: string
finished_at?: string
}
export interface TaskEvent {
id: number
task_id: string
from_state: string
to_state: string
message: string
created_at: string
}
export const deliveryApi = {
async listTargets(): Promise<DeliveryTarget[]> {
const data = await authRequest('/auth/api/v1/delivery/targets?component=mysql')
return Array.isArray(data.items) ? data.items : []
},
async createMySQL(payload: CreateMySQLDeliveryPayload): Promise<DeliveryTask> {
const data = await authRequest('/auth/api/v1/delivery/mysql', {
method: 'POST',
headers: {
'Idempotency-Key': createIdempotencyKey(payload),
},
body: JSON.stringify(payload),
})
return data.task
},
async getTask(taskId: string): Promise<{ task: DeliveryTask; events: TaskEvent[] }> {
const data = await authRequest(`/auth/api/v1/delivery/tasks/${encodeURIComponent(taskId)}`)
return {
task: data.task,
events: Array.isArray(data.events) ? data.events : [],
}
},
async cancel(taskId: string): Promise<void> {
await authRequest(`/auth/api/v1/delivery/tasks/${encodeURIComponent(taskId)}/cancel`, {
method: 'POST',
})
},
}
function createIdempotencyKey(payload: CreateMySQLDeliveryPayload) {
return [
'mysql',
payload.business_line_id,
payload.target_id,
payload.namespace,
payload.instance_name,
Date.now(),
].join(':')
}
async function authRequest(path: string, init: RequestInit = {}) {
const token = getToken()
const response = await fetch(path, {
...init,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...init.headers,
},
})
const text = await response.text()
const data = parseResponseBody(text)
if (!response.ok) {
const message = data?.error || data?.message || text || `HTTP ${response.status}`
throw new Error(message)
}
return data || {}
}
function parseResponseBody(text: string) {
if (!text.trim()) {
return {}
}
try {
return JSON.parse(text)
} catch {
return { error: text }
}
}
-68
View File
@@ -1,68 +0,0 @@
import { getToken } from '@/utils/auth'
export interface DeploymentCreatePayload {
component: string
business_line_id: number
params: Record<string, unknown>
}
export interface DeploymentCreateResult {
deployment_id: string
status: string
}
export const deploymentApi = {
async create(payload: DeploymentCreatePayload): Promise<DeploymentCreateResult> {
const data = await authRequest('/auth/api/v1/deployments', {
method: 'POST',
body: JSON.stringify(payload),
})
return {
deployment_id: String(data.deployment_id || ''),
status: String(data.status || ''),
}
},
async cancel(deploymentId: string): Promise<void> {
await authRequest(`/auth/api/v1/deployments/${encodeURIComponent(deploymentId)}/cancel`, {
method: 'POST',
})
},
eventsURL(deploymentId: string): string {
const token = getToken()
const params = token ? `?access_token=${encodeURIComponent(token)}` : ''
return `/auth/api/v1/deployments/${encodeURIComponent(deploymentId)}/events${params}`
},
}
async function authRequest(path: string, init: RequestInit = {}) {
const token = getToken()
const response = await fetch(path, {
...init,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...init.headers,
},
})
const text = await response.text()
const data = parseResponseBody(text)
if (!response.ok) {
const message = data?.error || data?.message || text || `HTTP ${response.status}`
throw new Error(message)
}
return data || {}
}
function parseResponseBody(text: string) {
if (!text.trim()) {
return {}
}
try {
return JSON.parse(text)
} catch {
return { error: text }
}
}
+81
View File
@@ -0,0 +1,81 @@
import { getToken } from '@/utils/auth'
export interface TaskLogSummary {
id: string
source: 'awx' | 'wayne'
service: string
name: string
runner: string
status: string
status_text: string
status_class: string
business_line_id: number
reference_id: string
created_at: string
updated_at: string
}
export interface TaskLogLine {
time: string
message: string
class: string
}
export interface TaskLogListParams {
source?: string
businessLineId?: number
}
export const taskLogApi = {
async list(params: TaskLogListParams = {}): Promise<TaskLogSummary[]> {
const query = new URLSearchParams()
if (params.source && params.source !== 'all') {
query.set('source', params.source)
}
if (params.businessLineId) {
query.set('business_line_id', String(params.businessLineId))
}
const suffix = query.toString() ? `?${query.toString()}` : ''
const data = await authRequest(`/auth/api/v1/task-logs${suffix}`)
return Array.isArray(data.items) ? data.items : []
},
async get(id: string): Promise<{ task: TaskLogSummary; lines: TaskLogLine[] }> {
const data = await authRequest(`/auth/api/v1/task-logs/${encodeURIComponent(id)}`)
return {
task: data.task,
lines: Array.isArray(data.lines) ? data.lines : [],
}
},
}
async function authRequest(path: string, init: RequestInit = {}) {
const token = getToken()
const response = await fetch(path, {
...init,
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
...(token ? { Authorization: `Bearer ${token}` } : {}),
...init.headers,
},
})
const text = await response.text()
const data = parseResponseBody(text)
if (!response.ok) {
const message = data?.error || data?.message || text || `HTTP ${response.status}`
throw new Error(message)
}
return data || {}
}
function parseResponseBody(text: string) {
if (!text.trim()) {
return {}
}
try {
return JSON.parse(text)
} catch {
return { error: text }
}
}