Add health checks

This commit is contained in:
Owen
2025-08-03 18:43:43 -07:00
parent e8612c7e6b
commit 289cce3a22
3 changed files with 46 additions and 25 deletions

View File

@@ -32,7 +32,7 @@ func (s Status) String() string {
// Config holds the health check configuration for a target
type Config struct {
ID string `json:"id"`
ID int `json:"id"`
Enabled bool `json:"hcEnabled"`
Path string `json:"hcPath"`
Scheme string `json:"hcScheme"`
@@ -59,11 +59,11 @@ type Target struct {
}
// StatusChangeCallback is called when any target's status changes
type StatusChangeCallback func(targets map[string]*Target)
type StatusChangeCallback func(targets map[int]*Target)
// Monitor manages health check targets and their monitoring
type Monitor struct {
targets map[string]*Target
targets map[int]*Target
mutex sync.RWMutex
callback StatusChangeCallback
client *http.Client
@@ -72,7 +72,7 @@ type Monitor struct {
// NewMonitor creates a new health check monitor
func NewMonitor(callback StatusChangeCallback) *Monitor {
return &Monitor{
targets: make(map[string]*Target),
targets: make(map[int]*Target),
callback: callback,
client: &http.Client{
Timeout: 30 * time.Second,
@@ -118,7 +118,7 @@ func (m *Monitor) AddTargets(configs []Config) error {
for _, config := range configs {
if err := m.addTargetUnsafe(config); err != nil {
return fmt.Errorf("failed to add target %s: %v", config.ID, err)
return fmt.Errorf("failed to add target %d: %v", config.ID, err)
}
}
@@ -183,13 +183,13 @@ func (m *Monitor) addTargetUnsafe(config Config) error {
}
// RemoveTarget removes a health check target
func (m *Monitor) RemoveTarget(id string) error {
func (m *Monitor) RemoveTarget(id int) error {
m.mutex.Lock()
defer m.mutex.Unlock()
target, exists := m.targets[id]
if !exists {
return fmt.Errorf("target with id %s not found", id)
return fmt.Errorf("target with id %d not found", id)
}
target.cancel()
@@ -204,11 +204,11 @@ func (m *Monitor) RemoveTarget(id string) error {
}
// RemoveTargets removes multiple health check targets
func (m *Monitor) RemoveTargets(ids []string) error {
func (m *Monitor) RemoveTargets(ids []int) error {
m.mutex.Lock()
defer m.mutex.Unlock()
var notFound []string
var notFound []int
for _, id := range ids {
target, exists := m.targets[id]
@@ -234,20 +234,20 @@ func (m *Monitor) RemoveTargets(ids []string) error {
}
// RemoveTargetsByID is a convenience method that accepts either a single ID or multiple IDs
func (m *Monitor) RemoveTargetsByID(ids ...string) error {
func (m *Monitor) RemoveTargetsByID(ids ...int) error {
return m.RemoveTargets(ids)
}
// GetTargets returns a copy of all targets
func (m *Monitor) GetTargets() map[string]*Target {
func (m *Monitor) GetTargets() map[int]*Target {
m.mutex.RLock()
defer m.mutex.RUnlock()
return m.getAllTargetsUnsafe()
}
// getAllTargetsUnsafe returns a copy of all targets without acquiring the mutex (internal method)
func (m *Monitor) getAllTargetsUnsafe() map[string]*Target {
targets := make(map[string]*Target)
func (m *Monitor) getAllTargetsUnsafe() map[int]*Target {
targets := make(map[int]*Target)
for id, target := range m.targets {
// Create a copy to avoid race conditions
targetCopy := *target
@@ -257,7 +257,7 @@ func (m *Monitor) getAllTargetsUnsafe() map[string]*Target {
}
// getAllTargets returns a copy of all targets (deprecated, use GetTargets)
func (m *Monitor) getAllTargets() map[string]*Target {
func (m *Monitor) getAllTargets() map[int]*Target {
return m.GetTargets()
}
@@ -363,17 +363,17 @@ func (m *Monitor) Stop() {
for _, target := range m.targets {
target.cancel()
}
m.targets = make(map[string]*Target)
m.targets = make(map[int]*Target)
}
// EnableTarget enables monitoring for a specific target
func (m *Monitor) EnableTarget(id string) error {
func (m *Monitor) EnableTarget(id int) error {
m.mutex.Lock()
defer m.mutex.Unlock()
target, exists := m.targets[id]
if !exists {
return fmt.Errorf("target with id %s not found", id)
return fmt.Errorf("target with id %d not found", id)
}
if !target.Config.Enabled {
@@ -391,13 +391,13 @@ func (m *Monitor) EnableTarget(id string) error {
}
// DisableTarget disables monitoring for a specific target
func (m *Monitor) DisableTarget(id string) error {
func (m *Monitor) DisableTarget(id int) error {
m.mutex.Lock()
defer m.mutex.Unlock()
target, exists := m.targets[id]
if !exists {
return fmt.Errorf("target with id %s not found", id)
return fmt.Errorf("target with id %d not found", id)
}
if target.Config.Enabled {

15
main.go
View File

@@ -338,6 +338,9 @@ func main() {
connected = false
}
// print out the data
logger.Debug("Received registration message data: %+v", msg.Data)
jsonData, err := json.Marshal(msg.Data)
if err != nil {
logger.Info("Error marshaling data: %v", err)
@@ -905,11 +908,11 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub
})
// Initialize health check monitor with status change callback
healthMonitor = healthcheck.NewMonitor(func(targets map[string]*healthcheck.Target) {
healthMonitor = healthcheck.NewMonitor(func(targets map[int]*healthcheck.Target) {
logger.Debug("Health check status update for %d targets", len(targets))
// Send health status update to the server
healthStatuses := make(map[string]interface{})
healthStatuses := make(map[int]interface{})
for id, target := range targets {
healthStatuses[id] = map[string]interface{}{
"status": target.Status.String(),
@@ -963,7 +966,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub
logger.Debug("Received health check remove request: %+v", msg)
type HealthCheckConfig struct {
IDs []string `json:"ids"`
IDs []int `json:"ids"`
}
var requestData HealthCheckConfig
@@ -991,7 +994,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub
logger.Debug("Received health check enable request: %+v", msg)
var requestData struct {
ID string `json:"id"`
ID int `json:"id"`
}
jsonData, err := json.Marshal(msg.Data)
if err != nil {
@@ -1016,7 +1019,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub
logger.Debug("Received health check disable request: %+v", msg)
var requestData struct {
ID string `json:"id"`
ID int `json:"id"`
}
jsonData, err := json.Marshal(msg.Data)
if err != nil {
@@ -1041,7 +1044,7 @@ persistent_keepalive_interval=5`, fixKey(privateKey.String()), fixKey(wgData.Pub
logger.Debug("Received health check status request")
targets := healthMonitor.GetTargets()
healthStatuses := make(map[string]interface{})
healthStatuses := make(map[int]interface{})
for id, target := range targets {
healthStatuses[id] = map[string]interface{}{
"status": target.Status.String(),

View File

@@ -205,6 +205,15 @@ func (c *Client) getToken() (string, error) {
}
}
// Check for environment variable to skip TLS verification
if os.Getenv("SKIP_TLS_VERIFY") == "true" {
if tlsConfig == nil {
tlsConfig = &tls.Config{}
}
tlsConfig.InsecureSkipVerify = true
logger.Debug("TLS certificate verification disabled via SKIP_TLS_VERIFY environment variable")
}
var tokenData map[string]interface{}
// Get a new token
@@ -339,6 +348,15 @@ func (c *Client) establishConnection() error {
}
dialer.TLSClientConfig = tlsConfig
}
// Check for environment variable to skip TLS verification for WebSocket connection
if os.Getenv("SKIP_TLS_VERIFY") == "true" {
if dialer.TLSClientConfig == nil {
dialer.TLSClientConfig = &tls.Config{}
}
dialer.TLSClientConfig.InsecureSkipVerify = true
logger.Debug("WebSocket TLS certificate verification disabled via SKIP_TLS_VERIFY environment variable")
}
conn, _, err := dialer.Dial(u.String(), nil)
if err != nil {
return fmt.Errorf("failed to connect to WebSocket: %w", err)