fix: Complete AgentHealth improvements and build fixes
- Update Update scanner default from 15min to 12 hours (backend) - Add 1 week and 2 week frequency options (frontend) - Rename AgentScanners to AgentHealth component - Add OS-aware package manager badges (APT, DNF, Windows/Winget, Docker) - Fix all build errors (types, imports, storage metrics) - Add useMemo optimization for enabled/auto-run counts
This commit is contained in:
@@ -20,14 +20,14 @@ import (
|
||||
|
||||
// Client handles API communication with the server
|
||||
type Client struct {
|
||||
baseURL string
|
||||
token string
|
||||
http *http.Client
|
||||
RapidPollingEnabled bool
|
||||
RapidPollingUntil time.Time
|
||||
machineID string // Cached machine ID for security binding
|
||||
eventBuffer *event.Buffer
|
||||
agentID uuid.UUID
|
||||
baseURL string
|
||||
token string
|
||||
http *http.Client
|
||||
RapidPollingEnabled bool
|
||||
RapidPollingUntil time.Time
|
||||
machineID string // Cached machine ID for security binding
|
||||
eventBuffer *event.Buffer
|
||||
agentID uuid.UUID
|
||||
}
|
||||
|
||||
// NewClient creates a new API client
|
||||
@@ -54,13 +54,13 @@ func NewClient(baseURL, token string) *Client {
|
||||
func NewClientWithEventBuffer(baseURL, token string, statePath string, agentID uuid.UUID) *Client {
|
||||
client := NewClient(baseURL, token)
|
||||
client.agentID = agentID
|
||||
|
||||
|
||||
// Initialize event buffer if state path is provided
|
||||
if statePath != "" {
|
||||
eventBufferPath := filepath.Join(statePath, "events_buffer.json")
|
||||
client.eventBuffer = event.NewBuffer(eventBufferPath)
|
||||
}
|
||||
|
||||
|
||||
return client
|
||||
}
|
||||
|
||||
@@ -121,22 +121,22 @@ func (c *Client) SetToken(token string) {
|
||||
|
||||
// RegisterRequest is the payload for agent registration
|
||||
type RegisterRequest struct {
|
||||
Hostname string `json:"hostname"`
|
||||
OSType string `json:"os_type"`
|
||||
OSVersion string `json:"os_version"`
|
||||
OSArchitecture string `json:"os_architecture"`
|
||||
AgentVersion string `json:"agent_version"`
|
||||
RegistrationToken string `json:"registration_token,omitempty"` // Fallback method
|
||||
MachineID string `json:"machine_id"`
|
||||
PublicKeyFingerprint string `json:"public_key_fingerprint"`
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
Hostname string `json:"hostname"`
|
||||
OSType string `json:"os_type"`
|
||||
OSVersion string `json:"os_version"`
|
||||
OSArchitecture string `json:"os_architecture"`
|
||||
AgentVersion string `json:"agent_version"`
|
||||
RegistrationToken string `json:"registration_token,omitempty"` // Fallback method
|
||||
MachineID string `json:"machine_id"`
|
||||
PublicKeyFingerprint string `json:"public_key_fingerprint"`
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
}
|
||||
|
||||
// RegisterResponse is returned after successful registration
|
||||
type RegisterResponse struct {
|
||||
AgentID uuid.UUID `json:"agent_id"`
|
||||
Token string `json:"token"` // Short-lived access token (24h)
|
||||
RefreshToken string `json:"refresh_token"` // Long-lived refresh token (90d)
|
||||
Token string `json:"token"` // Short-lived access token (24h)
|
||||
RefreshToken string `json:"refresh_token"` // Long-lived refresh token (90d)
|
||||
Config map[string]interface{} `json:"config"`
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ func (c *Client) Register(req RegisterRequest) (*RegisterResponse, error) {
|
||||
c.bufferEvent("registration_failure", "marshal_error", "error", "client",
|
||||
fmt.Sprintf("Failed to marshal registration request: %v", err),
|
||||
map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"error": err.Error(),
|
||||
"hostname": req.Hostname,
|
||||
})
|
||||
return nil, err
|
||||
@@ -168,7 +168,7 @@ func (c *Client) Register(req RegisterRequest) (*RegisterResponse, error) {
|
||||
c.bufferEvent("registration_failure", "request_creation_error", "error", "client",
|
||||
fmt.Sprintf("Failed to create registration request: %v", err),
|
||||
map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"error": err.Error(),
|
||||
"hostname": req.Hostname,
|
||||
})
|
||||
return nil, err
|
||||
@@ -187,8 +187,8 @@ func (c *Client) Register(req RegisterRequest) (*RegisterResponse, error) {
|
||||
c.bufferEvent("registration_failure", "network_error", "error", "client",
|
||||
fmt.Sprintf("Registration request failed: %v", err),
|
||||
map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"hostname": req.Hostname,
|
||||
"error": err.Error(),
|
||||
"hostname": req.Hostname,
|
||||
"server_url": c.baseURL,
|
||||
})
|
||||
return nil, err
|
||||
@@ -198,15 +198,15 @@ func (c *Client) Register(req RegisterRequest) (*RegisterResponse, error) {
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
||||
errorMsg := fmt.Sprintf("registration failed: %s - %s", resp.Status, string(bodyBytes))
|
||||
|
||||
|
||||
// Buffer registration failure event
|
||||
c.bufferEvent("registration_failure", "api_error", "error", "client",
|
||||
errorMsg,
|
||||
map[string]interface{}{
|
||||
"status_code": resp.StatusCode,
|
||||
"status_code": resp.StatusCode,
|
||||
"response_body": string(bodyBytes),
|
||||
"hostname": req.Hostname,
|
||||
"server_url": c.baseURL,
|
||||
"hostname": req.Hostname,
|
||||
"server_url": c.baseURL,
|
||||
})
|
||||
return nil, fmt.Errorf(errorMsg)
|
||||
}
|
||||
@@ -217,7 +217,7 @@ func (c *Client) Register(req RegisterRequest) (*RegisterResponse, error) {
|
||||
c.bufferEvent("registration_failure", "decode_error", "error", "client",
|
||||
fmt.Sprintf("Failed to decode registration response: %v", err),
|
||||
map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"error": err.Error(),
|
||||
"hostname": req.Hostname,
|
||||
})
|
||||
return nil, err
|
||||
@@ -239,7 +239,7 @@ type TokenRenewalRequest struct {
|
||||
|
||||
// TokenRenewalResponse is returned after successful token renewal
|
||||
type TokenRenewalResponse struct {
|
||||
Token string `json:"token"` // New short-lived access token (24h)
|
||||
Token string `json:"token"` // New short-lived access token (24h)
|
||||
}
|
||||
|
||||
// RenewToken uses refresh token to get a new access token (proper implementation)
|
||||
@@ -258,7 +258,7 @@ func (c *Client) RenewToken(agentID uuid.UUID, refreshToken string, agentVersion
|
||||
c.bufferEvent("token_renewal_failure", "marshal_error", "error", "client",
|
||||
fmt.Sprintf("Failed to marshal token renewal request: %v", err),
|
||||
map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"error": err.Error(),
|
||||
"agent_id": agentID.String(),
|
||||
})
|
||||
return err
|
||||
@@ -270,7 +270,7 @@ func (c *Client) RenewToken(agentID uuid.UUID, refreshToken string, agentVersion
|
||||
c.bufferEvent("token_renewal_failure", "request_creation_error", "error", "client",
|
||||
fmt.Sprintf("Failed to create token renewal request: %v", err),
|
||||
map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"error": err.Error(),
|
||||
"agent_id": agentID.String(),
|
||||
})
|
||||
return err
|
||||
@@ -283,8 +283,8 @@ func (c *Client) RenewToken(agentID uuid.UUID, refreshToken string, agentVersion
|
||||
c.bufferEvent("token_renewal_failure", "network_error", "error", "client",
|
||||
fmt.Sprintf("Token renewal request failed: %v", err),
|
||||
map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"agent_id": agentID.String(),
|
||||
"error": err.Error(),
|
||||
"agent_id": agentID.String(),
|
||||
"server_url": c.baseURL,
|
||||
})
|
||||
return err
|
||||
@@ -294,15 +294,15 @@ func (c *Client) RenewToken(agentID uuid.UUID, refreshToken string, agentVersion
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
bodyBytes, _ := io.ReadAll(resp.Body)
|
||||
errorMsg := fmt.Sprintf("token renewal failed: %s - %s", resp.Status, string(bodyBytes))
|
||||
|
||||
|
||||
// Buffer token renewal failure event
|
||||
c.bufferEvent("token_renewal_failure", "api_error", "error", "client",
|
||||
errorMsg,
|
||||
map[string]interface{}{
|
||||
"status_code": resp.StatusCode,
|
||||
"status_code": resp.StatusCode,
|
||||
"response_body": string(bodyBytes),
|
||||
"agent_id": agentID.String(),
|
||||
"server_url": c.baseURL,
|
||||
"agent_id": agentID.String(),
|
||||
"server_url": c.baseURL,
|
||||
})
|
||||
return fmt.Errorf(errorMsg)
|
||||
}
|
||||
@@ -313,7 +313,7 @@ func (c *Client) RenewToken(agentID uuid.UUID, refreshToken string, agentVersion
|
||||
c.bufferEvent("token_renewal_failure", "decode_error", "error", "client",
|
||||
fmt.Sprintf("Failed to decode token renewal response: %v", err),
|
||||
map[string]interface{}{
|
||||
"error": err.Error(),
|
||||
"error": err.Error(),
|
||||
"agent_id": agentID.String(),
|
||||
})
|
||||
return err
|
||||
@@ -327,10 +327,10 @@ func (c *Client) RenewToken(agentID uuid.UUID, refreshToken string, agentVersion
|
||||
|
||||
// Command represents a command from the server
|
||||
type Command struct {
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Params map[string]interface{} `json:"params"`
|
||||
Signature string `json:"signature,omitempty"` // Ed25519 signature of the command
|
||||
ID string `json:"id"`
|
||||
Type string `json:"type"`
|
||||
Params map[string]interface{} `json:"params"`
|
||||
Signature string `json:"signature,omitempty"` // Ed25519 signature of the command
|
||||
}
|
||||
|
||||
// CommandItem is an alias for Command for consistency with server models
|
||||
@@ -338,9 +338,9 @@ type CommandItem = Command
|
||||
|
||||
// CommandsResponse contains pending commands
|
||||
type CommandsResponse struct {
|
||||
Commands []Command `json:"commands"`
|
||||
RapidPolling *RapidPollingConfig `json:"rapid_polling,omitempty"`
|
||||
AcknowledgedIDs []string `json:"acknowledged_ids,omitempty"` // IDs server has received
|
||||
Commands []Command `json:"commands"`
|
||||
RapidPolling *RapidPollingConfig `json:"rapid_polling,omitempty"`
|
||||
AcknowledgedIDs []string `json:"acknowledged_ids,omitempty"` // IDs server has received
|
||||
}
|
||||
|
||||
// RapidPollingConfig contains rapid polling configuration from server
|
||||
@@ -351,16 +351,16 @@ type RapidPollingConfig struct {
|
||||
|
||||
// SystemMetrics represents lightweight system metrics sent with check-ins
|
||||
type SystemMetrics struct {
|
||||
CPUPercent float64 `json:"cpu_percent,omitempty"`
|
||||
MemoryPercent float64 `json:"memory_percent,omitempty"`
|
||||
MemoryUsedGB float64 `json:"memory_used_gb,omitempty"`
|
||||
MemoryTotalGB float64 `json:"memory_total_gb,omitempty"`
|
||||
DiskUsedGB float64 `json:"disk_used_gb,omitempty"`
|
||||
DiskTotalGB float64 `json:"disk_total_gb,omitempty"`
|
||||
DiskPercent float64 `json:"disk_percent,omitempty"`
|
||||
Uptime string `json:"uptime,omitempty"`
|
||||
Version string `json:"version,omitempty"` // Agent version
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty"` // Additional metadata
|
||||
CPUPercent float64 `json:"cpu_percent,omitempty"`
|
||||
MemoryPercent float64 `json:"memory_percent,omitempty"`
|
||||
MemoryUsedGB float64 `json:"memory_used_gb,omitempty"`
|
||||
MemoryTotalGB float64 `json:"memory_total_gb,omitempty"`
|
||||
DiskUsedGB float64 `json:"disk_used_gb,omitempty"`
|
||||
DiskTotalGB float64 `json:"disk_total_gb,omitempty"`
|
||||
DiskPercent float64 `json:"disk_percent,omitempty"`
|
||||
Uptime string `json:"uptime,omitempty"`
|
||||
Version string `json:"version,omitempty"` // Agent version
|
||||
Metadata map[string]interface{} `json:"metadata,omitempty"` // Additional metadata
|
||||
|
||||
// Command acknowledgment tracking
|
||||
PendingAcknowledgments []string `json:"pending_acknowledgments,omitempty"` // Command IDs awaiting ACK
|
||||
@@ -427,9 +427,9 @@ func (c *Client) GetCommands(agentID uuid.UUID, metrics *SystemMetrics) (*Comman
|
||||
|
||||
// UpdateReport represents discovered updates
|
||||
type UpdateReport struct {
|
||||
CommandID string `json:"command_id"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Updates []UpdateReportItem `json:"updates"`
|
||||
CommandID string `json:"command_id"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Updates []UpdateReportItem `json:"updates"`
|
||||
}
|
||||
|
||||
// UpdateReportItem represents a single update
|
||||
@@ -480,20 +480,20 @@ func (c *Client) ReportUpdates(agentID uuid.UUID, report UpdateReport) error {
|
||||
|
||||
// MetricsReport represents metrics data (storage, system, CPU, memory)
|
||||
type MetricsReport struct {
|
||||
CommandID string `json:"command_id"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
CommandID string `json:"command_id"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Metrics []MetricsReportItem `json:"metrics"`
|
||||
}
|
||||
|
||||
// MetricsReportItem represents a single metric
|
||||
type MetricsReportItem struct {
|
||||
PackageType string `json:"package_type"`
|
||||
PackageName string `json:"package_name"`
|
||||
CurrentVersion string `json:"current_version"`
|
||||
AvailableVersion string `json:"available_version"`
|
||||
Severity string `json:"severity"`
|
||||
RepositorySource string `json:"repository_source"`
|
||||
Metadata map[string]interface{} `json:"metadata"`
|
||||
PackageType string `json:"package_type"`
|
||||
PackageName string `json:"package_name"`
|
||||
CurrentVersion string `json:"current_version"`
|
||||
AvailableVersion string `json:"available_version"`
|
||||
Severity string `json:"severity"`
|
||||
RepositorySource string `json:"repository_source"`
|
||||
Metadata map[string]interface{} `json:"metadata"`
|
||||
}
|
||||
|
||||
// ReportMetrics sends metrics data to the server
|
||||
@@ -529,20 +529,20 @@ func (c *Client) ReportMetrics(agentID uuid.UUID, report MetricsReport) error {
|
||||
|
||||
// DockerReport represents Docker image information
|
||||
type DockerReport struct {
|
||||
CommandID string `json:"command_id"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
CommandID string `json:"command_id"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Images []DockerReportItem `json:"images"`
|
||||
}
|
||||
|
||||
// DockerReportItem represents a single Docker image
|
||||
type DockerReportItem struct {
|
||||
PackageType string `json:"package_type"`
|
||||
PackageName string `json:"package_name"`
|
||||
CurrentVersion string `json:"current_version"`
|
||||
AvailableVersion string `json:"available_version"`
|
||||
Severity string `json:"severity"`
|
||||
RepositorySource string `json:"repository_source"`
|
||||
Metadata map[string]interface{} `json:"metadata"`
|
||||
PackageType string `json:"package_type"`
|
||||
PackageName string `json:"package_name"`
|
||||
CurrentVersion string `json:"current_version"`
|
||||
AvailableVersion string `json:"available_version"`
|
||||
Severity string `json:"severity"`
|
||||
RepositorySource string `json:"repository_source"`
|
||||
Metadata map[string]interface{} `json:"metadata"`
|
||||
}
|
||||
|
||||
// ReportDockerImages sends Docker image information to the server
|
||||
@@ -577,7 +577,7 @@ func (c *Client) ReportDockerImages(agentID uuid.UUID, report DockerReport) erro
|
||||
}
|
||||
|
||||
// ReportStorageMetrics sends storage metrics to the server via dedicated endpoint
|
||||
func (c *Client) ReportStorageMetrics(agentID uuid.UUID, report StorageMetricReport) error {
|
||||
func (c *Client) ReportStorageMetrics(agentID uuid.UUID, report models.StorageMetricReport) error {
|
||||
url := fmt.Sprintf("%s/api/v1/agents/%s/storage-metrics", c.baseURL, agentID)
|
||||
|
||||
body, err := json.Marshal(report)
|
||||
@@ -652,26 +652,26 @@ func (c *Client) ReportLog(agentID uuid.UUID, report LogReport) error {
|
||||
|
||||
// DependencyReport represents a dependency report after dry run
|
||||
type DependencyReport struct {
|
||||
PackageName string `json:"package_name"`
|
||||
PackageType string `json:"package_type"`
|
||||
Dependencies []string `json:"dependencies"`
|
||||
UpdateID string `json:"update_id"`
|
||||
DryRunResult *InstallResult `json:"dry_run_result,omitempty"`
|
||||
PackageName string `json:"package_name"`
|
||||
PackageType string `json:"package_type"`
|
||||
Dependencies []string `json:"dependencies"`
|
||||
UpdateID string `json:"update_id"`
|
||||
DryRunResult *InstallResult `json:"dry_run_result,omitempty"`
|
||||
}
|
||||
|
||||
// InstallResult represents the result of a package installation attempt
|
||||
type InstallResult struct {
|
||||
Success bool `json:"success"`
|
||||
ErrorMessage string `json:"error_message,omitempty"`
|
||||
Stdout string `json:"stdout,omitempty"`
|
||||
Stderr string `json:"stderr,omitempty"`
|
||||
ExitCode int `json:"exit_code"`
|
||||
DurationSeconds int `json:"duration_seconds"`
|
||||
Action string `json:"action,omitempty"`
|
||||
Stdout string `json:"stdout,omitempty"`
|
||||
Stderr string `json:"stderr,omitempty"`
|
||||
ExitCode int `json:"exit_code"`
|
||||
DurationSeconds int `json:"duration_seconds"`
|
||||
Action string `json:"action,omitempty"`
|
||||
PackagesInstalled []string `json:"packages_installed,omitempty"`
|
||||
ContainersUpdated []string `json:"containers_updated,omitempty"`
|
||||
Dependencies []string `json:"dependencies,omitempty"`
|
||||
IsDryRun bool `json:"is_dry_run"`
|
||||
IsDryRun bool `json:"is_dry_run"`
|
||||
}
|
||||
|
||||
// ReportDependencies sends dependency report to the server
|
||||
@@ -707,7 +707,7 @@ func (c *Client) ReportDependencies(agentID uuid.UUID, report DependencyReport)
|
||||
|
||||
// SystemInfoReport represents system information updates
|
||||
type SystemInfoReport struct {
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
CPUModel string `json:"cpu_model,omitempty"`
|
||||
CPUCores int `json:"cpu_cores,omitempty"`
|
||||
CPUThreads int `json:"cpu_threads,omitempty"`
|
||||
|
||||
@@ -7,7 +7,7 @@ type SubsystemConfig struct {
|
||||
// Execution settings
|
||||
Enabled bool `json:"enabled"`
|
||||
Timeout time.Duration `json:"timeout"` // Timeout for this subsystem
|
||||
|
||||
|
||||
// Interval for this subsystem (in minutes)
|
||||
// This controls how often the server schedules scans for this subsystem
|
||||
IntervalMinutes int `json:"interval_minutes,omitempty"`
|
||||
@@ -51,16 +51,16 @@ func GetDefaultSubsystemsConfig() SubsystemsConfig {
|
||||
// Default circuit breaker config
|
||||
defaultCB := CircuitBreakerConfig{
|
||||
Enabled: true,
|
||||
FailureThreshold: 3, // 3 consecutive failures
|
||||
FailureThreshold: 3, // 3 consecutive failures
|
||||
FailureWindow: 10 * time.Minute, // within 10 minutes
|
||||
OpenDuration: 30 * time.Minute, // circuit open for 30 min
|
||||
HalfOpenAttempts: 2, // 2 successful attempts to close circuit
|
||||
HalfOpenAttempts: 2, // 2 successful attempts to close circuit
|
||||
}
|
||||
|
||||
// Aggressive circuit breaker for Windows Update (known to be slow/problematic)
|
||||
windowsCB := CircuitBreakerConfig{
|
||||
Enabled: true,
|
||||
FailureThreshold: 2, // Only 2 failures
|
||||
FailureThreshold: 2, // Only 2 failures
|
||||
FailureWindow: 15 * time.Minute,
|
||||
OpenDuration: 60 * time.Minute, // Open for 1 hour
|
||||
HalfOpenAttempts: 3,
|
||||
@@ -68,15 +68,15 @@ func GetDefaultSubsystemsConfig() SubsystemsConfig {
|
||||
|
||||
return SubsystemsConfig{
|
||||
System: SubsystemConfig{
|
||||
Enabled: true, // System scanner always available
|
||||
Enabled: true, // System scanner always available
|
||||
Timeout: 10 * time.Second, // System info should be fast
|
||||
IntervalMinutes: 5, // Default: 5 minutes
|
||||
IntervalMinutes: 5, // Default: 5 minutes
|
||||
CircuitBreaker: defaultCB,
|
||||
},
|
||||
Updates: SubsystemConfig{
|
||||
Enabled: true, // Virtual subsystem for package update scheduling
|
||||
Timeout: 0, // Not used - delegates to individual package scanners
|
||||
IntervalMinutes: 15, // Default: 15 minutes
|
||||
Enabled: true, // Virtual subsystem for package update scheduling
|
||||
Timeout: 0, // Not used - delegates to individual package scanners
|
||||
IntervalMinutes: 720, // Default: 12 hours (more reasonable for update checks)
|
||||
CircuitBreaker: CircuitBreakerConfig{Enabled: false}, // No circuit breaker for virtual subsystem
|
||||
},
|
||||
APT: SubsystemConfig{
|
||||
@@ -88,31 +88,31 @@ func GetDefaultSubsystemsConfig() SubsystemsConfig {
|
||||
DNF: SubsystemConfig{
|
||||
Enabled: true,
|
||||
Timeout: 15 * time.Minute, // TODO: Make scanner timeouts user-adjustable via settings. DNF operations can take a long time on large systems
|
||||
IntervalMinutes: 15, // Default: 15 minutes
|
||||
IntervalMinutes: 15, // Default: 15 minutes
|
||||
CircuitBreaker: defaultCB,
|
||||
},
|
||||
Docker: SubsystemConfig{
|
||||
Enabled: true,
|
||||
Timeout: 60 * time.Second, // Registry queries can be slow
|
||||
IntervalMinutes: 15, // Default: 15 minutes
|
||||
IntervalMinutes: 15, // Default: 15 minutes
|
||||
CircuitBreaker: defaultCB,
|
||||
},
|
||||
Windows: SubsystemConfig{
|
||||
Enabled: true,
|
||||
Timeout: 10 * time.Minute, // Windows Update can be VERY slow
|
||||
IntervalMinutes: 15, // Default: 15 minutes
|
||||
IntervalMinutes: 15, // Default: 15 minutes
|
||||
CircuitBreaker: windowsCB,
|
||||
},
|
||||
Winget: SubsystemConfig{
|
||||
Enabled: true,
|
||||
Timeout: 2 * time.Minute, // Winget has multiple retry strategies
|
||||
IntervalMinutes: 15, // Default: 15 minutes
|
||||
IntervalMinutes: 15, // Default: 15 minutes
|
||||
CircuitBreaker: defaultCB,
|
||||
},
|
||||
Storage: SubsystemConfig{
|
||||
Enabled: true,
|
||||
Timeout: 10 * time.Second, // Disk info should be fast
|
||||
IntervalMinutes: 5, // Default: 5 minutes
|
||||
IntervalMinutes: 5, // Default: 5 minutes
|
||||
CircuitBreaker: defaultCB,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/Fimeg/RedFlag/aggregator-agent/internal/client"
|
||||
"github.com/Fimeg/RedFlag/aggregator-agent/internal/system"
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user