This commit includes comprehensive codebase cleanup and refactoring: ## Code Cleanup - Remove dead TypeScript code (types/monitoring.ts - 194 lines duplicate) - Remove unused Go functions (GetClusterNodes, MigratePassword, GetClusterHealthInfo) - Clean up commented-out code blocks across multiple files - Remove unused TypeScript exports (helpTextClass, private tag color helpers) - Delete obsolete test files and components ## localStorage Consolidation - Centralize all storage keys into STORAGE_KEYS constant - Update 5 files to use centralized keys: * utils/apiClient.ts (AUTH, LEGACY_TOKEN) * components/Dashboard/Dashboard.tsx (GUEST_METADATA) * components/Docker/DockerHosts.tsx (DOCKER_METADATA) * App.tsx (PLATFORMS_SEEN) * stores/updates.ts (UPDATES) - Benefits: Single source of truth, prevents typos, better maintainability ## Previous Work Committed - Docker monitoring improvements and disk metrics - Security enhancements and setup fixes - API refactoring and cleanup - Documentation updates - Build system improvements ## Testing - All frontend tests pass (29 tests) - All Go tests pass (15 packages) - Production build successful - Zero breaking changes Total: 186 files changed, 5825 insertions(+), 11602 deletions(-)
146 lines
3.9 KiB
Go
146 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"strings"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/hostagent"
|
|
"github.com/rcourtman/pulse-go-rewrite/internal/utils"
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
type multiValue []string
|
|
|
|
func (m *multiValue) String() string {
|
|
return strings.Join(*m, ",")
|
|
}
|
|
|
|
func (m *multiValue) Set(value string) error {
|
|
*m = append(*m, value)
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
cfg := loadConfig()
|
|
|
|
logger := zerolog.New(os.Stdout).With().Timestamp().Logger()
|
|
cfg.Logger = &logger
|
|
|
|
// Check if we should run as a Windows service
|
|
if err := runAsWindowsService(cfg, logger); err != nil {
|
|
logger.Fatal().Err(err).Msg("Windows service failed")
|
|
}
|
|
|
|
// If runAsWindowsService returns nil without error, we're not running as a service
|
|
// or we're on a non-Windows platform, so run normally
|
|
agent, err := hostagent.New(cfg)
|
|
if err != nil {
|
|
logger.Fatal().Err(err).Msg("failed to initialise host agent")
|
|
}
|
|
|
|
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
|
defer cancel()
|
|
|
|
logger.Info().
|
|
Str("pulse_url", cfg.PulseURL).
|
|
Str("agent_id", cfg.AgentID).
|
|
Dur("interval", cfg.Interval).
|
|
Msg("Starting Pulse host agent")
|
|
|
|
if err := agent.Run(ctx); err != nil && err != context.Canceled {
|
|
logger.Fatal().Err(err).Msg("host agent terminated with error")
|
|
}
|
|
|
|
logger.Info().Msg("Host agent stopped")
|
|
}
|
|
|
|
func loadConfig() hostagent.Config {
|
|
envURL := utils.GetenvTrim("PULSE_URL")
|
|
envToken := utils.GetenvTrim("PULSE_TOKEN")
|
|
envInterval := utils.GetenvTrim("PULSE_INTERVAL")
|
|
envHostname := utils.GetenvTrim("PULSE_HOSTNAME")
|
|
envAgentID := utils.GetenvTrim("PULSE_AGENT_ID")
|
|
envInsecure := utils.GetenvTrim("PULSE_INSECURE_SKIP_VERIFY")
|
|
envTags := utils.GetenvTrim("PULSE_TAGS")
|
|
envRunOnce := utils.GetenvTrim("PULSE_ONCE")
|
|
|
|
defaultInterval := 30 * time.Second
|
|
if envInterval != "" {
|
|
if parsed, err := time.ParseDuration(envInterval); err == nil {
|
|
defaultInterval = parsed
|
|
}
|
|
}
|
|
|
|
urlFlag := flag.String("url", envURL, "Pulse server URL (e.g. https://pulse.example.com)")
|
|
tokenFlag := flag.String("token", envToken, "Pulse API token (required)")
|
|
intervalFlag := flag.Duration("interval", defaultInterval, "Reporting interval (e.g. 30s, 1m)")
|
|
hostnameFlag := flag.String("hostname", envHostname, "Override hostname reported to Pulse")
|
|
agentIDFlag := flag.String("agent-id", envAgentID, "Override agent identifier")
|
|
insecureFlag := flag.Bool("insecure", utils.ParseBool(envInsecure), "Skip TLS certificate verification")
|
|
runOnceFlag := flag.Bool("once", utils.ParseBool(envRunOnce), "Collect and send a single report, then exit")
|
|
showVersion := flag.Bool("version", false, "Print the agent version and exit")
|
|
|
|
var tagFlags multiValue
|
|
flag.Var(&tagFlags, "tag", "Tag to apply to this host (repeatable)")
|
|
|
|
flag.Parse()
|
|
|
|
if *showVersion {
|
|
fmt.Println(hostagent.Version)
|
|
os.Exit(0)
|
|
}
|
|
|
|
pulseURL := strings.TrimSpace(*urlFlag)
|
|
if pulseURL == "" {
|
|
pulseURL = "http://localhost:7655"
|
|
}
|
|
|
|
token := strings.TrimSpace(*tokenFlag)
|
|
if token == "" {
|
|
fmt.Fprintln(os.Stderr, "error: Pulse API token is required (via --token or PULSE_TOKEN)")
|
|
os.Exit(1)
|
|
}
|
|
|
|
interval := *intervalFlag
|
|
if interval <= 0 {
|
|
interval = 30 * time.Second
|
|
}
|
|
|
|
tags := gatherTags(envTags, tagFlags)
|
|
|
|
return hostagent.Config{
|
|
PulseURL: pulseURL,
|
|
APIToken: token,
|
|
Interval: interval,
|
|
HostnameOverride: strings.TrimSpace(*hostnameFlag),
|
|
AgentID: strings.TrimSpace(*agentIDFlag),
|
|
Tags: tags,
|
|
InsecureSkipVerify: *insecureFlag,
|
|
RunOnce: *runOnceFlag,
|
|
}
|
|
}
|
|
|
|
func gatherTags(env string, flags []string) []string {
|
|
tags := make([]string, 0)
|
|
if env != "" {
|
|
for _, tag := range strings.Split(env, ",") {
|
|
tag = strings.TrimSpace(tag)
|
|
if tag != "" {
|
|
tags = append(tags, tag)
|
|
}
|
|
}
|
|
}
|
|
for _, tag := range flags {
|
|
tag = strings.TrimSpace(tag)
|
|
if tag != "" {
|
|
tags = append(tags, tag)
|
|
}
|
|
}
|
|
return tags
|
|
}
|