Add agent operations history and manual links

This commit is contained in:
Maxim
2026-08-07 22:24:44 +03:00
parent c50b4cf986
commit 21b4f528e0
9 changed files with 565 additions and 43 deletions

View File

@@ -86,37 +86,38 @@ type AgentIssue struct {
}
type AgentReport struct {
Hostname string `json:"hostname"`
MachineID string `json:"machineId"`
Version string `json:"version"`
OS string `json:"os"`
Arch string `json:"arch"`
OSName string `json:"osName"`
Kernel string `json:"kernel"`
UptimeSeconds int64 `json:"uptimeSeconds"`
Load1 float64 `json:"load1"`
CPUPercent float64 `json:"cpuPercent"`
MemoryTotal uint64 `json:"memoryTotal"`
MemoryUsed uint64 `json:"memoryUsed"`
SwapTotal uint64 `json:"swapTotal"`
SwapUsed uint64 `json:"swapUsed"`
RootTotal uint64 `json:"rootTotal"`
RootUsed uint64 `json:"rootUsed"`
DockerAvailable bool `json:"dockerAvailable"`
DockerError string `json:"dockerError,omitempty"`
Containers []AgentContainer `json:"containers"`
Interfaces []AgentInterface `json:"interfaces"`
Services []AgentService `json:"services"`
Issues []AgentIssue `json:"issues"`
Processes []AgentProcess `json:"processes"`
Filesystems []AgentFilesystem `json:"filesystems"`
ListenPorts []AgentListenPort `json:"listenPorts"`
Pressure AgentPressure `json:"pressure"`
OOMKills []AgentLog `json:"oomKills"`
UpdatesAvailable int `json:"updatesAvailable"`
RebootRequired bool `json:"rebootRequired"`
InventoryAt int64 `json:"inventoryAt"`
CollectedAt int64 `json:"collectedAt"`
Hostname string `json:"hostname"`
MachineID string `json:"machineId"`
Version string `json:"version"`
OS string `json:"os"`
Arch string `json:"arch"`
OSName string `json:"osName"`
Kernel string `json:"kernel"`
UptimeSeconds int64 `json:"uptimeSeconds"`
Load1 float64 `json:"load1"`
CPUPercent float64 `json:"cpuPercent"`
MemoryTotal uint64 `json:"memoryTotal"`
MemoryUsed uint64 `json:"memoryUsed"`
SwapTotal uint64 `json:"swapTotal"`
SwapUsed uint64 `json:"swapUsed"`
RootTotal uint64 `json:"rootTotal"`
RootUsed uint64 `json:"rootUsed"`
DockerAvailable bool `json:"dockerAvailable"`
DockerError string `json:"dockerError,omitempty"`
Containers []AgentContainer `json:"containers"`
Interfaces []AgentInterface `json:"interfaces"`
Services []AgentService `json:"services"`
Issues []AgentIssue `json:"issues"`
Processes []AgentProcess `json:"processes"`
Filesystems []AgentFilesystem `json:"filesystems"`
ListenPorts []AgentListenPort `json:"listenPorts"`
Pressure AgentPressure `json:"pressure"`
OOMKills []AgentLog `json:"oomKills"`
UpdatesAvailable int `json:"updatesAvailable"`
RebootRequired bool `json:"rebootRequired"`
InventoryAt int64 `json:"inventoryAt"`
CollectedAt int64 `json:"collectedAt"`
ActionResults []AgentActionResult `json:"actionResults,omitempty"`
}
type agentInventory struct {
@@ -137,6 +138,7 @@ type AgentUpdateManifest struct {
type agentReportResponse struct {
Accepted bool `json:"accepted"`
Update *AgentUpdateManifest `json:"update,omitempty"`
Commands []AgentCommand `json:"commands,omitempty"`
}
var guestInventory struct {
@@ -150,6 +152,11 @@ var guestIssues struct {
collectedAt time.Time
}
var guestActionResults struct {
sync.Mutex
value []AgentActionResult
}
var agentBinaryInfo struct {
sync.Once
manifest AgentUpdateManifest
@@ -258,6 +265,8 @@ func (s *Store) SaveAgentReport(id, secret, remote string, report AgentReport) e
if !s.AuthenticateAgent(id, secret) {
return errors.New("агент не авторизован")
}
s.CompleteAgentActions(id, report.ActionResults)
report.ActionResults = nil
data, _ := json.Marshal(report)
_, err := s.db.Exec(`UPDATE agents SET hostname=?,version=?,last_seen=?,report_json=?,remote_address=? WHERE id=?`, report.Hostname, report.Version, time.Now().Unix(), string(data), remote, id)
return err
@@ -325,6 +334,9 @@ func runGuestAgent(opts agentOptions) error {
client := &http.Client{Timeout: 12 * time.Second}
for {
report := collectAgentReport()
guestActionResults.Lock()
report.ActionResults = append([]AgentActionResult(nil), guestActionResults.value...)
guestActionResults.Unlock()
data, _ := json.Marshal(report)
req, _ := http.NewRequest(http.MethodPost, config.Server+"/api/agent/report", bytes.NewReader(data))
req.Header.Set("Content-Type", "application/json")
@@ -351,7 +363,23 @@ func runGuestAgent(opts agentOptions) error {
}
if response.StatusCode == http.StatusOK {
var result agentReportResponse
if json.Unmarshal(responseData, &result) == nil && result.Update != nil && newerAgentVersion(result.Update.Version, version) {
if json.Unmarshal(responseData, &result) == nil {
if len(report.ActionResults) > 0 {
guestActionResults.Lock()
guestActionResults.value = nil
guestActionResults.Unlock()
}
if len(result.Commands) > 0 {
executed := make([]AgentActionResult, 0, len(result.Commands))
for _, command := range result.Commands {
executed = append(executed, executeAgentCommand(command))
}
guestActionResults.Lock()
guestActionResults.value = append(guestActionResults.value, executed...)
guestActionResults.Unlock()
}
}
if result.Update != nil && newerAgentVersion(result.Update.Version, version) {
if updateErr := applyAgentUpdate(client, config, *result.Update); updateErr != nil {
requestErr = fmt.Errorf("автообновление: %v", updateErr)
} else {