Files
pulse/internal/api/types.go
T
rcourtman 30fa3fd810 feat: add complete Proxmox Mail Gateway (PMG) monitoring support
Add comprehensive PMG monitoring with mail statistics, queue depth tracking,
spam distribution analysis, and quarantine monitoring. Includes full discovery
support and UI consistency improvements across all Proxmox products.

Backend:
- Add pkg/pmg package with complete API client for PMG operations
- Implement mail statistics collection (inbound/outbound, spam, virus, bounces)
- Add queue depth monitoring (active, deferred, hold, incoming queues)
- Support spam score distribution and quarantine totals
- Add PMG-specific discovery logic to differentiate from PVE on port 8006
- Extend mock data generator with realistic PMG instances and metrics
- Add PMG node configuration support in config system

Frontend:
- Create MailGateway.tsx component with detailed PMG dashboard
- Display mail flow statistics with time-series charts
- Show queue depth with color-coded warnings (>50 messages or >30min age)
- Add spam distribution histogram and quarantine status
- Support cluster node status with individual queue monitoring
- Add PMG to network discovery with purple branding and mail icon
- Implement conditional navigation (hide PMG tab when no instances configured)
- Standardize discovery UI controls across PVE/PBS/PMG settings pages

API:
- Add /api/config/pmg endpoints for node configuration
- Support PMG-specific monitoring toggles (mail stats, queues, quarantine)
- Extend system settings with PMG configuration options

Discovery:
- Detect PMG vs PVE on shared port 8006 using /api2/json/statistics/mail endpoint
- Return 'pmg' type for mail gateway servers in discovery results
- Update DiscoveryModal to display PMG servers with appropriate styling

This completes ecosystem monitoring support for all three Proxmox products:
Proxmox VE, Proxmox Backup Server, and Proxmox Mail Gateway.
2025-10-10 14:30:51 +00:00

398 lines
13 KiB
Go

package api
import (
"time"
"github.com/rcourtman/pulse-go-rewrite/internal/models"
"github.com/rcourtman/pulse-go-rewrite/internal/types"
)
// Common response types for API endpoints
// HealthResponse represents the health check response
type HealthResponse struct {
Status string `json:"status"`
Timestamp int64 `json:"timestamp"`
Uptime float64 `json:"uptime"`
}
// VersionResponse represents version information
type VersionResponse struct {
Version string `json:"version"`
BuildTime string `json:"buildTime,omitempty"`
GoVersion string `json:"goVersion,omitempty"`
UpdateAvailable bool `json:"updateAvailable"`
LatestVersion string `json:"latestVersion,omitempty"`
}
// ErrorResponse represents an error response
type ErrorResponse struct {
Error string `json:"error"`
Message string `json:"message,omitempty"`
Code int `json:"code,omitempty"`
}
// SuccessResponse represents a generic success response
type SuccessResponse struct {
Success bool `json:"success"`
Message string `json:"message,omitempty"`
}
// StateResponse represents the full state response
type StateResponse struct {
Nodes []models.Node `json:"nodes"`
VMs []models.VM `json:"vms"`
Containers []models.Container `json:"containers"`
DockerHosts []models.DockerHostFrontend `json:"dockerHosts"`
Storage []models.Storage `json:"storage"`
CephClusters []models.CephCluster `json:"cephClusters"`
PBSInstances []models.PBSInstance `json:"pbs"`
PMGInstances []models.PMGInstance `json:"pmg"`
PBSBackups []models.PBSBackup `json:"pbsBackups"`
Metrics []models.Metric `json:"metrics"`
PVEBackups models.PVEBackups `json:"pveBackups"`
Performance models.Performance `json:"performance"`
ConnectionHealth map[string]bool `json:"connectionHealth"`
Stats models.Stats `json:"stats"`
ActiveAlerts []models.Alert `json:"activeAlerts"`
RecentlyResolved []models.ResolvedAlert `json:"recentlyResolved"`
LastUpdate time.Time `json:"lastUpdate"`
}
// ConfigResponse represents configuration response
type ConfigResponse struct {
Nodes []NodeConfig `json:"nodes"`
Settings SettingsConfig `json:"settings"`
}
// NodeConfig represents a node configuration
type NodeConfig struct {
ID string `json:"id"`
Name string `json:"name"`
Type string `json:"type"`
Address string `json:"address"`
Port int `json:"port,omitempty"`
Username string `json:"username,omitempty"`
HasPassword bool `json:"hasPassword"`
HasToken bool `json:"hasToken"`
SkipTLS bool `json:"skipTLS,omitempty"`
Tags []string `json:"tags,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
// SettingsConfig represents application settings
type SettingsConfig struct {
CheckInterval int `json:"checkInterval"`
RetentionDays int `json:"retentionDays"`
Theme string `json:"theme,omitempty"`
TimeZone string `json:"timezone,omitempty"`
NotificationsOn bool `json:"notificationsOn"`
}
// NodeRequest represents a request to create/update a node
type NodeRequest struct {
Name string `json:"name" validate:"required,min=1,max=100"`
Type string `json:"type" validate:"required,oneof=proxmox pve pbs pmg"`
Address string `json:"address" validate:"required,ip|hostname"`
Port int `json:"port,omitempty" validate:"omitempty,min=1,max=65535"`
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
Token string `json:"token,omitempty"`
SkipTLS bool `json:"skipTLS,omitempty"`
Tags []string `json:"tags,omitempty"`
Metadata map[string]string `json:"metadata,omitempty"`
}
// SettingsRequest represents a request to update settings
type SettingsRequest struct {
CheckInterval *int `json:"checkInterval,omitempty" validate:"omitempty,min=10,max=3600"`
RetentionDays *int `json:"retentionDays,omitempty" validate:"omitempty,min=1,max=365"`
Theme *string `json:"theme,omitempty" validate:"omitempty,oneof=light dark auto"`
TimeZone *string `json:"timezone,omitempty"`
NotificationsOn *bool `json:"notificationsOn,omitempty"`
}
// BackupResponse represents backup information
type BackupResponse struct {
Backups []BackupInfo `json:"backups"`
Total int `json:"total"`
}
// BackupInfo represents a single backup
type BackupInfo struct {
ID string `json:"id"`
VMID string `json:"vmid"`
Name string `json:"name"`
Type string `json:"type"`
Size int64 `json:"size"`
Time time.Time `json:"time"`
Node string `json:"node"`
Storage string `json:"storage,omitempty"`
Status string `json:"status"`
Notes string `json:"notes,omitempty"`
}
// MetricsResponse represents metrics data
type MetricsResponse struct {
Metrics map[string]MetricData `json:"metrics"`
Period string `json:"period"`
}
// MetricData represents metric data points
type MetricData struct {
Values []float64 `json:"values"`
Timestamps []time.Time `json:"timestamps"`
Unit string `json:"unit,omitempty"`
}
// StorageResponse represents storage information
type StorageResponse struct {
Storage []StorageInfo `json:"storage"`
Total StorageTotals `json:"totals"`
}
// StorageInfo represents storage details
type StorageInfo struct {
ID string `json:"id"`
Node string `json:"node"`
Storage string `json:"storage"`
Type string `json:"type"`
Status string `json:"status"`
Total int64 `json:"total"`
Used int64 `json:"used"`
Available int64 `json:"available"`
Percentage float64 `json:"percentage"`
}
// StorageTotals represents aggregate storage metrics
type StorageTotals struct {
Total int64 `json:"total"`
Used int64 `json:"used"`
Available int64 `json:"available"`
Percentage float64 `json:"percentage"`
}
// ChartResponse represents chart data
type ChartResponse struct {
ChartData map[string]VMChartData `json:"data"`
NodeData map[string]NodeChartData `json:"nodeData"`
StorageData map[string]StorageChartData `json:"storageData"`
Timestamp int64 `json:"timestamp"`
Stats ChartStats `json:"stats"`
}
// ChartStats represents chart statistics
type ChartStats struct {
OldestDataTimestamp int64 `json:"oldestDataTimestamp"`
}
// VMChartData represents chart data for a VM
type VMChartData map[string][]MetricPoint
// NodeChartData represents chart data for a node
type NodeChartData map[string][]MetricPoint
// StorageChartData represents chart data for storage
type StorageChartData map[string][]MetricPoint
// StorageChartsResponse represents storage charts API response
type StorageChartsResponse map[string]StorageMetrics
// StorageMetrics represents storage metrics data
type StorageMetrics struct {
Usage []types.MetricPoint `json:"usage"`
Used []types.MetricPoint `json:"used"`
Total []types.MetricPoint `json:"total"`
Avail []types.MetricPoint `json:"avail"`
}
// MetricPoint represents a single metric data point
type MetricPoint struct {
Timestamp int64 `json:"timestamp"`
Value float64 `json:"value"`
}
// ChartData represents data for a single chart
type ChartData struct {
Labels []string `json:"labels"`
Datasets []Dataset `json:"datasets"`
}
// Dataset represents a chart dataset
type Dataset struct {
Label string `json:"label"`
Data []float64 `json:"data"`
BackgroundColor string `json:"backgroundColor,omitempty"`
BorderColor string `json:"borderColor,omitempty"`
}
// DiagnosticsResponse represents system diagnostics
type DiagnosticsResponse struct {
System SystemInfo `json:"system"`
Connections []ConnectionInfo `json:"connections"`
Errors []ErrorInfo `json:"errors"`
Performance PerformanceInfo `json:"performance"`
}
// SystemInfo represents system information
type SystemInfo struct {
Hostname string `json:"hostname"`
OS string `json:"os"`
Arch string `json:"arch"`
CPUCount int `json:"cpuCount"`
Memory int64 `json:"memory"`
GoVersion string `json:"goVersion"`
Uptime float64 `json:"uptime"`
StartTime time.Time `json:"startTime"`
}
// ConnectionInfo represents connection status
type ConnectionInfo struct {
Node string `json:"node"`
Type string `json:"type"`
Address string `json:"address"`
Status string `json:"status"`
Latency time.Duration `json:"latency,omitempty"`
LastSeen time.Time `json:"lastSeen,omitempty"`
Error string `json:"error,omitempty"`
}
// ErrorInfo represents error information
type ErrorInfo struct {
Time time.Time `json:"time"`
Level string `json:"level"`
Message string `json:"message"`
Source string `json:"source,omitempty"`
}
// PerformanceInfo represents performance metrics
type PerformanceInfo struct {
CPUUsage float64 `json:"cpuUsage"`
MemoryUsage int64 `json:"memoryUsage"`
Goroutines int `json:"goroutines"`
RequestRate float64 `json:"requestRate"`
ErrorRate float64 `json:"errorRate"`
}
// SecurityStatusResponse represents security configuration status
type SecurityStatusResponse struct {
Configured bool `json:"configured"`
Method string `json:"method"`
RequiresSetup bool `json:"requiresSetup"`
DeploymentType string `json:"deploymentType,omitempty"`
}
// ExportRequest represents a configuration export request
type ExportRequest struct {
Passphrase string `json:"passphrase" validate:"required,min=8"`
IncludeCredentials bool `json:"includeCredentials,omitempty"`
}
// ImportRequest represents a configuration import request
type ImportRequest struct {
Data string `json:"data" validate:"required"`
Passphrase string `json:"passphrase" validate:"required"`
Overwrite bool `json:"overwrite,omitempty"`
}
// NotificationTestRequest represents a notification test request
type NotificationTestRequest struct {
Type string `json:"type" validate:"required,oneof=webhook discord slack email"`
Config map[string]interface{} `json:"config" validate:"required"`
Message string `json:"message,omitempty"`
}
// UpdateCheckResponse represents update availability
type UpdateCheckResponse struct {
CurrentVersion string `json:"currentVersion"`
LatestVersion string `json:"latestVersion"`
UpdateAvailable bool `json:"updateAvailable"`
ReleaseNotes string `json:"releaseNotes,omitempty"`
ReleaseDate time.Time `json:"releaseDate,omitempty"`
DownloadURL string `json:"downloadUrl,omitempty"`
}
// WebSocketMessage represents a WebSocket message
type WebSocketMessage struct {
Type string `json:"type"`
Data interface{} `json:"data"`
Timestamp time.Time `json:"timestamp"`
}
// LoginRequest represents a login request (if implemented)
type LoginRequest struct {
Username string `json:"username" validate:"required"`
Password string `json:"password" validate:"required"`
}
// LoginResponse represents a login response
type LoginResponse struct {
Success bool `json:"success"`
Token string `json:"token,omitempty"`
Message string `json:"message,omitempty"`
}
// TestConnectionResponse represents a connection test result
type TestConnectionResponse struct {
Status string `json:"status"`
Message string `json:"message"`
Latency int64 `json:"latency,omitempty"`
Details string `json:"details,omitempty"`
}
// NodeConnectionResponse represents node connection result
type NodeConnectionResponse struct {
Status string `json:"status"`
Message string `json:"message"`
Nodes int `json:"nodes,omitempty"`
}
// DiscoveryResponse represents discovery results
type DiscoveryResponse struct {
Servers []DiscoveredServer `json:"servers"`
Errors []string `json:"errors"`
Cached bool `json:"cached"`
UpdatedAt time.Time `json:"updatedAt,omitempty"`
}
// DiscoveredServer represents a discovered server
type DiscoveredServer struct {
IP string `json:"ip"`
Port int `json:"port"`
Type string `json:"type"`
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
Status string `json:"status,omitempty"`
}
// AutoRegisterResponse represents auto-registration response
type AutoRegisterResponse struct {
Status string `json:"status"`
Message string `json:"message"`
TokenID string `json:"tokenId,omitempty"`
TokenName string `json:"tokenName,omitempty"`
}
// ConfigImportResponse represents import response
type ConfigImportResponse struct {
Status string `json:"status"`
Message string `json:"message"`
}
// ConfigExportResponse represents export response
type ConfigExportResponse struct {
Status string `json:"status"`
Data string `json:"data"`
}
// InstallScriptResponse represents install script response
type InstallScriptResponse struct {
URL string `json:"url"`
Command string `json:"command"`
}
// AgentVersionResponse represents Docker agent version information
type AgentVersionResponse struct {
Version string `json:"version"`
}