From db9bcd56871c89b55fd519ebbc2fe9ab46b800da Mon Sep 17 00:00:00 2001 From: Cody Lee Date: Thu, 22 Dec 2022 17:44:39 -0600 Subject: [PATCH 1/2] add new interface for testing --- pkg/datadogunifi/datadog.go | 17 ++++++++++++++ pkg/influxunifi/influxdb.go | 46 +++++++++++++++++++++++++++++++++++++ pkg/inputunifi/interface.go | 41 +++++++++++++++++++++++++++++++++ pkg/lokiunifi/logger.go | 12 +++++++--- pkg/lokiunifi/loki.go | 22 ++++++++++++++++-- pkg/lokiunifi/report_ids.go | 2 +- pkg/mysqlunifi/main.go | 13 +++++++++++ pkg/poller/inputs.go | 1 + pkg/poller/outputs.go | 1 + pkg/promunifi/collector.go | 25 ++++++++++++++++++++ pkg/webserver/server.go | 27 ++++++++++++++++++++++ 11 files changed, 201 insertions(+), 6 deletions(-) diff --git a/pkg/datadogunifi/datadog.go b/pkg/datadogunifi/datadog.go index e9811f7e..924a0d09 100644 --- a/pkg/datadogunifi/datadog.go +++ b/pkg/datadogunifi/datadog.go @@ -3,6 +3,7 @@ package datadogunifi import ( + "fmt" "reflect" "time" @@ -203,6 +204,22 @@ func (u *DatadogUnifi) Enabled() bool { return *u.Enable } +func (u *DatadogUnifi) DebugOutput(l poller.Logger) (bool, error) { + if u == nil { + return true, nil + } + if !u.Enabled() { + return true, nil + } + u.setConfigDefaults() + var err error + u.datadog, err = statsd.New(u.Address, u.options...) + if err != nil { + return false, fmt.Errorf("Error configuration Datadog agent reporting: %+v", err) + } + return true, nil +} + // Run runs a ticker to poll the unifi server and update Datadog. func (u *DatadogUnifi) Run(c poller.Collect) error { u.Collector = c diff --git a/pkg/influxunifi/influxdb.go b/pkg/influxunifi/influxdb.go index 9da3ab61..b0459438 100644 --- a/pkg/influxunifi/influxdb.go +++ b/pkg/influxunifi/influxdb.go @@ -16,6 +16,7 @@ import ( "github.com/unpoller/unifi" "github.com/unpoller/unpoller/pkg/poller" "github.com/unpoller/unpoller/pkg/webserver" + "golang.org/x/net/context" "golift.io/cnfg" ) @@ -142,6 +143,51 @@ func (u *InfluxUnifi) Enabled() bool { return !u.Disable } +func (u *InfluxUnifi) DebugOutput(l poller.Logger) (bool, error) { + if u == nil { + return true, nil + } + if !u.Enabled() { + return true, nil + } + u.setConfigDefaults() + _, err := url.Parse(u.Config.URL) + if err != nil { + return false, fmt.Errorf("invalid influx URL: %v", err) + } + + if u.IsVersion2 { + // we're a version 2 + tlsConfig := &tls.Config{InsecureSkipVerify: !u.VerifySSL} // nolint: gosec + serverOptions := influx.DefaultOptions().SetTLSConfig(tlsConfig).SetBatchSize(u.BatchSize) + u.influxV2 = influx.NewClientWithOptions(u.URL, u.AuthToken, serverOptions) + ctx, cancel := context.WithTimeout(context.Background(), time.Second*2) + defer cancel() + ok, err := u.influxV2.Ping(ctx) + if err != nil { + return false, err + } + if !ok { + return false, fmt.Errorf("unsuccessful ping to influxdb2") + } + } else { + u.influxV1, err = influxV1.NewHTTPClient(influxV1.HTTPConfig{ + Addr: u.URL, + Username: u.User, + Password: u.Pass, + TLSConfig: &tls.Config{InsecureSkipVerify: !u.VerifySSL}, // nolint: gosec + }) + if err != nil { + return false, fmt.Errorf("making client: %w", err) + } + _, _, err = u.influxV1.Ping(time.Second * 2) + if err != nil { + return false, fmt.Errorf("unsuccessful ping to influxdb1") + } + } + return true, nil +} + // Run runs a ticker to poll the unifi server and update influxdb. func (u *InfluxUnifi) Run(c poller.Collect) error { u.Collector = c diff --git a/pkg/inputunifi/interface.go b/pkg/inputunifi/interface.go index 337814c7..1833bb48 100644 --- a/pkg/inputunifi/interface.go +++ b/pkg/inputunifi/interface.go @@ -57,6 +57,47 @@ func (u *InputUnifi) Initialize(l poller.Logger) error { return nil } +func (u *InputUnifi) DebugInputs(l poller.Logger) (bool, error) { + if u == nil || u.Config == nil { + return true, nil + } + if u.setDefaults(&u.Default); len(u.Controllers) == 0 && !u.Dynamic { + u.Controllers = []*Controller{&u.Default} + } + + if len(u.Controllers) == 0 { + u.Logf("No controllers configured. Polling dynamic controllers only! Defaults:") + u.logController(&u.Default) + } + + ok := true + var allErrors error + for i, c := range u.Controllers { + if err := u.getUnifi(u.setControllerDefaults(c)); err != nil { + u.LogErrorf("Controller %d of %d Auth or Connection Error, retrying: %v", i+1, len(u.Controllers), err) + ok = false + if allErrors != nil { + err = fmt.Errorf("%v: %w", err, allErrors) + } + continue + } + + if err := u.checkSites(c); err != nil { + u.LogErrorf("checking sites on %s: %v", c.URL, err) + ok = false + if allErrors != nil { + err = fmt.Errorf("%v: %w", err, allErrors) + } + continue + } + + u.Logf("Valid UniFi Controller %d of %d:", i+1, len(u.Controllers)) + u.logController(c) + } + + return ok, allErrors +} + func (u *InputUnifi) logController(c *Controller) { u.Logf(" => URL: %s (verify SSL: %v)", c.URL, *c.VerifySSL) diff --git a/pkg/lokiunifi/logger.go b/pkg/lokiunifi/logger.go index ff8f554e..294ea25a 100644 --- a/pkg/lokiunifi/logger.go +++ b/pkg/lokiunifi/logger.go @@ -14,7 +14,9 @@ func (l *Loki) Logf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "info"}, }) - l.Collect.Logf(msg, v...) + if l.Collect != nil { + l.Collect.Logf(msg, v...) + } } // LogErrorf logs an error message. @@ -24,7 +26,9 @@ func (l *Loki) LogErrorf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "error"}, }) - l.Collect.LogErrorf(msg, v...) + if l.Collect != nil { + l.Collect.LogErrorf(msg, v...) + } } // LogDebugf logs a debug message. @@ -34,5 +38,7 @@ func (l *Loki) LogDebugf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "debug"}, }) - l.Collect.LogDebugf(msg, v...) + if l.Collect != nil { + l.Collect.LogDebugf(msg, v...) + } } diff --git a/pkg/lokiunifi/loki.go b/pkg/lokiunifi/loki.go index d02685e4..669a3711 100644 --- a/pkg/lokiunifi/loki.go +++ b/pkg/lokiunifi/loki.go @@ -76,6 +76,19 @@ func (l *Loki) Enabled() bool { return !l.Disable } +func (l *Loki) DebugOutput(logger poller.Logger) (bool, error) { + if l == nil { + return true, nil + } + if !l.Enabled() { + return true, nil + } + if err := l.ValidateConfig(); err != nil { + return false, err + } + return true, nil +} + // Run is fired from the poller library after the Config is unmarshalled. func (l *Loki) Run(collect poller.Collect) error { l.Collect = collect @@ -85,7 +98,10 @@ func (l *Loki) Run(collect poller.Collect) error { } l.Logf("Loki enabled") - l.ValidateConfig() + if err := l.ValidateConfig(); err != nil { + l.LogErrorf("invalid loki config") + return err + } fake := *l.Config fake.Password = strconv.FormatBool(fake.Password != "") @@ -99,7 +115,7 @@ func (l *Loki) Run(collect poller.Collect) error { // ValidateConfig sets initial "last" update time. Also creates an http client, // makes sure URL is sane, and sets interval within min/max limits. -func (l *Loki) ValidateConfig() { +func (l *Loki) ValidateConfig() error { if l.Interval.Duration > maxInterval { l.Interval.Duration = maxInterval } else if l.Interval.Duration < minInterval { @@ -110,6 +126,7 @@ func (l *Loki) ValidateConfig() { pass, err := os.ReadFile(strings.TrimPrefix(l.Password, "file://")) if err != nil { l.LogErrorf("Reading Loki Password File: %v", err) + return fmt.Errorf("error reading password file") } l.Password = strings.TrimSpace(string(pass)) @@ -118,6 +135,7 @@ func (l *Loki) ValidateConfig() { l.last = time.Now().Add(-l.Interval.Duration) l.client = l.httpClient() l.URL = strings.TrimRight(l.URL, "/") // gets a path appended to it later. + return nil } // PollController runs forever, polling UniFi for events and pushing them to Loki. diff --git a/pkg/lokiunifi/report_ids.go b/pkg/lokiunifi/report_ids.go index 5c2f4750..4629d253 100644 --- a/pkg/lokiunifi/report_ids.go +++ b/pkg/lokiunifi/report_ids.go @@ -15,7 +15,7 @@ func (r *Report) IDS(event *unifi.IDS, logs *Logs) { } r.Counts[typeIDS]++ // increase counter and append new log line. - + logs.Streams = append(logs.Streams, LogStream{ Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), event.Msg}}, Labels: CleanLabels(map[string]string{ diff --git a/pkg/mysqlunifi/main.go b/pkg/mysqlunifi/main.go index 7fbb2d76..74ce80a3 100644 --- a/pkg/mysqlunifi/main.go +++ b/pkg/mysqlunifi/main.go @@ -69,6 +69,19 @@ func (p *plugin) Enabled() bool { return !p.Disable } +func (p *plugin) DebugOutput(l poller.Logger) (bool, error) { + if p == nil { + return true, nil + } + if !p.Enabled() { + return true, nil + } + if err := p.validateConfig(); err != nil { + return false, err + } + return true, nil +} + // Run gets called by poller core code. Return when the plugin stops working or has an error. // In other words, don't run your code in a go routine, it already is. func (p *plugin) Run(c poller.Collect) error { diff --git a/pkg/poller/inputs.go b/pkg/poller/inputs.go index 1bb8bced..fea5a125 100644 --- a/pkg/poller/inputs.go +++ b/pkg/poller/inputs.go @@ -21,6 +21,7 @@ type Input interface { Metrics(*Filter) (*Metrics, error) // Called every time new metrics are requested. Events(*Filter) (*Events, error) // This is new. RawMetrics(*Filter) ([]byte, error) + DebugInputs(Logger) (bool, error) } // InputPlugin describes an input plugin's consumable interface. diff --git a/pkg/poller/outputs.go b/pkg/poller/outputs.go index 7785de7e..183b66e4 100644 --- a/pkg/poller/outputs.go +++ b/pkg/poller/outputs.go @@ -27,6 +27,7 @@ type Collect interface { type OutputPlugin interface { Run(Collect) error Enabled() bool + DebugOutput(Logger) (bool, error) } // Output defines the output data for a metric exporter like influx or prometheus. diff --git a/pkg/promunifi/collector.go b/pkg/promunifi/collector.go index e9414692..cfd070dc 100644 --- a/pkg/promunifi/collector.go +++ b/pkg/promunifi/collector.go @@ -3,7 +3,9 @@ package promunifi import ( "fmt" + "net" "net/http" + "net/url" "reflect" "strings" "sync" @@ -116,6 +118,29 @@ func init() { // nolint: gochecknoinits }) } +func (u *promUnifi) DebugOutput(l poller.Logger) (bool, error) { + if u == nil { + return true, nil + } + if !u.Enabled() { + return true, nil + } + if u.HTTPListen == "" { + return false, fmt.Errorf("invalid listen string") + } + // check the port + httpListenURL, err := url.Parse(u.HTTPListen) + if err != nil { + return false, err + } + ln, err := net.Listen("tcp", fmt.Sprintf("%s:%s", httpListenURL.Host, httpListenURL.Port())) + if err != nil { + return false, err + } + _ = ln.Close() + return false, nil +} + func (u *promUnifi) Enabled() bool { if u == nil { return false diff --git a/pkg/webserver/server.go b/pkg/webserver/server.go index dae24323..9d3be346 100644 --- a/pkg/webserver/server.go +++ b/pkg/webserver/server.go @@ -4,6 +4,7 @@ package webserver import ( "errors" "fmt" + "net" "net/http" "os" "path/filepath" @@ -94,6 +95,32 @@ func (s *Server) Run(c poller.Collect) error { return s.Start() } +func (s *Server) DebugOutput(l poller.Logger) (bool, error) { + if s == nil { + return true, nil + } + if !s.Enabled() { + return true, nil + } + if s.HTMLPath == "" { + return true, nil + } + + // check the html path + if _, err := os.Stat(s.HTMLPath); err != nil { + return false, fmt.Errorf("problem with HTML path: %w", err) + } + + // check the port + ln, err := net.Listen("tcp", fmt.Sprintf(":%d", s.Port)) + if err != nil { + return false, err + } + _ = ln.Close() + + return true, nil +} + // Start gets the web server going. func (s *Server) Start() (err error) { s.server = &http.Server{ From 3768c535120e3fb4c5c5d02e66f0947f3277c173 Mon Sep 17 00:00:00 2001 From: Cody Lee Date: Thu, 22 Dec 2022 18:16:43 -0600 Subject: [PATCH 2/2] CLI works --- pkg/datadogunifi/datadog.go | 2 +- pkg/influxunifi/influxdb.go | 2 +- pkg/influxunifi/logger.go | 12 ++++++--- pkg/inputunifi/interface.go | 18 ++++++++----- pkg/inputunifi/updateweb.go | 12 ++++++--- pkg/lokiunifi/loki.go | 2 +- pkg/mysqlunifi/main.go | 2 +- pkg/poller/commands.go | 54 +++++++++++++++++++++++++++++++++++++ pkg/poller/config.go | 1 + pkg/poller/inputs.go | 2 +- pkg/poller/outputs.go | 2 +- pkg/poller/start.go | 10 +++++++ pkg/promunifi/collector.go | 14 +++++----- pkg/promunifi/logger.go | 12 ++++++--- pkg/webserver/logger.go | 12 ++++++--- pkg/webserver/server.go | 2 +- 16 files changed, 126 insertions(+), 33 deletions(-) diff --git a/pkg/datadogunifi/datadog.go b/pkg/datadogunifi/datadog.go index 924a0d09..be875247 100644 --- a/pkg/datadogunifi/datadog.go +++ b/pkg/datadogunifi/datadog.go @@ -204,7 +204,7 @@ func (u *DatadogUnifi) Enabled() bool { return *u.Enable } -func (u *DatadogUnifi) DebugOutput(l poller.Logger) (bool, error) { +func (u *DatadogUnifi) DebugOutput() (bool, error) { if u == nil { return true, nil } diff --git a/pkg/influxunifi/influxdb.go b/pkg/influxunifi/influxdb.go index b0459438..eff554cd 100644 --- a/pkg/influxunifi/influxdb.go +++ b/pkg/influxunifi/influxdb.go @@ -143,7 +143,7 @@ func (u *InfluxUnifi) Enabled() bool { return !u.Disable } -func (u *InfluxUnifi) DebugOutput(l poller.Logger) (bool, error) { +func (u *InfluxUnifi) DebugOutput() (bool, error) { if u == nil { return true, nil } diff --git a/pkg/influxunifi/logger.go b/pkg/influxunifi/logger.go index 57806442..6148f77e 100644 --- a/pkg/influxunifi/logger.go +++ b/pkg/influxunifi/logger.go @@ -14,7 +14,9 @@ func (u *InfluxUnifi) Logf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "info"}, }) - u.Collector.Logf(msg, v...) + if u.Collector != nil { + u.Collector.Logf(msg, v...) + } } // LogErrorf logs an error message. @@ -24,7 +26,9 @@ func (u *InfluxUnifi) LogErrorf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "error"}, }) - u.Collector.LogErrorf(msg, v...) + if u.Collector != nil { + u.Collector.LogErrorf(msg, v...) + } } // LogDebugf logs a debug message. @@ -34,5 +38,7 @@ func (u *InfluxUnifi) LogDebugf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "debug"}, }) - u.Collector.LogDebugf(msg, v...) + if u.Collector != nil { + u.Collector.LogDebugf(msg, v...) + } } diff --git a/pkg/inputunifi/interface.go b/pkg/inputunifi/interface.go index 1833bb48..dd9b1e08 100644 --- a/pkg/inputunifi/interface.go +++ b/pkg/inputunifi/interface.go @@ -57,7 +57,7 @@ func (u *InputUnifi) Initialize(l poller.Logger) error { return nil } -func (u *InputUnifi) DebugInputs(l poller.Logger) (bool, error) { +func (u *InputUnifi) DebugInput() (bool, error) { if u == nil || u.Config == nil { return true, nil } @@ -70,23 +70,27 @@ func (u *InputUnifi) DebugInputs(l poller.Logger) (bool, error) { u.logController(&u.Default) } - ok := true + allOK := true var allErrors error for i, c := range u.Controllers { if err := u.getUnifi(u.setControllerDefaults(c)); err != nil { u.LogErrorf("Controller %d of %d Auth or Connection Error, retrying: %v", i+1, len(u.Controllers), err) - ok = false + allOK = false if allErrors != nil { - err = fmt.Errorf("%v: %w", err, allErrors) + allErrors = fmt.Errorf("%v: %w", err, allErrors) + } else { + allErrors = err } continue } if err := u.checkSites(c); err != nil { u.LogErrorf("checking sites on %s: %v", c.URL, err) - ok = false + allOK = false if allErrors != nil { - err = fmt.Errorf("%v: %w", err, allErrors) + allErrors = fmt.Errorf("%v: %w", err, allErrors) + } else { + allErrors = err } continue } @@ -95,7 +99,7 @@ func (u *InputUnifi) DebugInputs(l poller.Logger) (bool, error) { u.logController(c) } - return ok, allErrors + return allOK, allErrors } func (u *InputUnifi) logController(c *Controller) { diff --git a/pkg/inputunifi/updateweb.go b/pkg/inputunifi/updateweb.go index 18b5f0aa..c660690f 100644 --- a/pkg/inputunifi/updateweb.go +++ b/pkg/inputunifi/updateweb.go @@ -191,7 +191,9 @@ func (u *InputUnifi) Logf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "info"}, }) - u.Logger.Logf(msg, v...) + if u.Logger != nil { + u.Logger.Logf(msg, v...) + } } // LogErrorf logs an error message. @@ -201,7 +203,9 @@ func (u *InputUnifi) LogErrorf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "error"}, }) - u.Logger.LogErrorf(msg, v...) + if u.Logger != nil { + u.Logger.LogErrorf(msg, v...) + } } // LogDebugf logs a debug message. @@ -211,5 +215,7 @@ func (u *InputUnifi) LogDebugf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "debug"}, }) - u.Logger.LogDebugf(msg, v...) + if u.Logger != nil { + u.Logger.LogDebugf(msg, v...) + } } diff --git a/pkg/lokiunifi/loki.go b/pkg/lokiunifi/loki.go index 669a3711..d0a37cb0 100644 --- a/pkg/lokiunifi/loki.go +++ b/pkg/lokiunifi/loki.go @@ -76,7 +76,7 @@ func (l *Loki) Enabled() bool { return !l.Disable } -func (l *Loki) DebugOutput(logger poller.Logger) (bool, error) { +func (l *Loki) DebugOutput() (bool, error) { if l == nil { return true, nil } diff --git a/pkg/mysqlunifi/main.go b/pkg/mysqlunifi/main.go index 74ce80a3..5530513f 100644 --- a/pkg/mysqlunifi/main.go +++ b/pkg/mysqlunifi/main.go @@ -69,7 +69,7 @@ func (p *plugin) Enabled() bool { return !p.Disable } -func (p *plugin) DebugOutput(l poller.Logger) (bool, error) { +func (p *plugin) DebugOutput() (bool, error) { if p == nil { return true, nil } diff --git a/pkg/poller/commands.go b/pkg/poller/commands.go index e9b9f032..f50dfad1 100644 --- a/pkg/poller/commands.go +++ b/pkg/poller/commands.go @@ -54,3 +54,57 @@ func (u *UnifiPoller) PrintPasswordHash() (err error) { return err //nolint:wrapcheck } + +func (u *UnifiPoller) DebugIO() error { + inputSync.RLock() + defer inputSync.RUnlock() + outputSync.RLock() + defer outputSync.RUnlock() + + allOK := true + var allErr error + + u.Logf("Checking inputs...") + totalInputs := len(inputs) + for i, input := range inputs { + u.Logf("\t(%d/%d) Checking input %s...", i+1, totalInputs, input.Name) + ok, err := input.DebugInput() + if !ok { + u.LogErrorf("\t\t %s Failed: %v", input.Name, err) + allOK = false + } else { + u.Logf("\t\t %s is OK", input.Name) + } + if err != nil { + if allErr == nil { + allErr = err + } else { + allErr = fmt.Errorf("%v: %w", err, allErr) + } + } + } + + u.Logf("Checking outputs...") + totalOutputs := len(outputs) + for i, output := range outputs { + u.Logf("\t(%d/%d) Checking output %s...", i+1, totalOutputs, output.Name) + ok, err := output.DebugOutput() + if !ok { + u.LogErrorf("\t\t %s Failed: %v", output.Name, err) + allOK = false + } else { + u.Logf("\t\t %s is OK", output.Name) + } + if err != nil { + if allErr == nil { + allErr = err + } else { + allErr = fmt.Errorf("%v: %w", err, allErr) + } + } + } + if !allOK { + u.LogErrorf("No all checks passed, please fix the logged issues.") + } + return allErr +} diff --git a/pkg/poller/config.go b/pkg/poller/config.go index 2eb3242f..519299f6 100644 --- a/pkg/poller/config.go +++ b/pkg/poller/config.go @@ -72,6 +72,7 @@ type Flags struct { DumpJSON string HashPW string ShowVer bool + DebugIO bool *pflag.FlagSet } diff --git a/pkg/poller/inputs.go b/pkg/poller/inputs.go index fea5a125..65fc4c8f 100644 --- a/pkg/poller/inputs.go +++ b/pkg/poller/inputs.go @@ -21,7 +21,7 @@ type Input interface { Metrics(*Filter) (*Metrics, error) // Called every time new metrics are requested. Events(*Filter) (*Events, error) // This is new. RawMetrics(*Filter) ([]byte, error) - DebugInputs(Logger) (bool, error) + DebugInput() (bool, error) } // InputPlugin describes an input plugin's consumable interface. diff --git a/pkg/poller/outputs.go b/pkg/poller/outputs.go index 183b66e4..4f05ffc9 100644 --- a/pkg/poller/outputs.go +++ b/pkg/poller/outputs.go @@ -27,7 +27,7 @@ type Collect interface { type OutputPlugin interface { Run(Collect) error Enabled() bool - DebugOutput(Logger) (bool, error) + DebugOutput() (bool, error) } // Output defines the output data for a metric exporter like influx or prometheus. diff --git a/pkg/poller/start.go b/pkg/poller/start.go index ea204297..fae92743 100644 --- a/pkg/poller/start.go +++ b/pkg/poller/start.go @@ -48,6 +48,15 @@ func (u *UnifiPoller) Start() error { return err } + if u.Flags.DebugIO { + err = u.DebugIO() + if err != nil { + os.Exit(1) + } + log.Fatal("Failed debug checks") + return err + } + return u.Run() } @@ -63,6 +72,7 @@ func (f *Flags) Parse(args []string) { "This option bcrypts a provided string. Useful for the webserver password. Use - to be prompted.") f.StringVarP(&f.DumpJSON, "dumpjson", "j", "", "This debug option prints a json payload and exits. See man page for more info.") + f.BoolVarP(&f.DebugIO, "debugio", "d", false, "Debug the Inputs and Outputs configured and exit.") f.StringVarP(&f.ConfigFile, "config", "c", DefaultConfFile(), "Poller config file path. Separating multiple paths with a comma will load the first config file found.") f.BoolVarP(&f.ShowVer, "version", "v", false, "Print the version and exit.") diff --git a/pkg/promunifi/collector.go b/pkg/promunifi/collector.go index cfd070dc..f38dcd54 100644 --- a/pkg/promunifi/collector.go +++ b/pkg/promunifi/collector.go @@ -5,7 +5,6 @@ import ( "fmt" "net" "net/http" - "net/url" "reflect" "strings" "sync" @@ -118,7 +117,7 @@ func init() { // nolint: gochecknoinits }) } -func (u *promUnifi) DebugOutput(l poller.Logger) (bool, error) { +func (u *promUnifi) DebugOutput() (bool, error) { if u == nil { return true, nil } @@ -129,16 +128,17 @@ func (u *promUnifi) DebugOutput(l poller.Logger) (bool, error) { return false, fmt.Errorf("invalid listen string") } // check the port - httpListenURL, err := url.Parse(u.HTTPListen) - if err != nil { - return false, err + parts := strings.Split(u.HTTPListen, ":") + if len(parts) != 2 { + return false, fmt.Errorf("invalid listen address: %s (must be of the form \"IP:Port\"", u.HTTPListen) } - ln, err := net.Listen("tcp", fmt.Sprintf("%s:%s", httpListenURL.Host, httpListenURL.Port())) + + ln, err := net.Listen("tcp", u.HTTPListen) if err != nil { return false, err } _ = ln.Close() - return false, nil + return true, nil } func (u *promUnifi) Enabled() bool { diff --git a/pkg/promunifi/logger.go b/pkg/promunifi/logger.go index 8215fd51..242386bb 100644 --- a/pkg/promunifi/logger.go +++ b/pkg/promunifi/logger.go @@ -14,7 +14,9 @@ func (u *promUnifi) Logf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "info"}, }) - u.Collector.Logf(msg, v...) + if u.Collector != nil { + u.Collector.Logf(msg, v...) + } } // LogErrorf logs an error message. @@ -24,7 +26,9 @@ func (u *promUnifi) LogErrorf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "error"}, }) - u.Collector.LogErrorf(msg, v...) + if u.Collector != nil { + u.Collector.LogErrorf(msg, v...) + } } // LogDebugf logs a debug message. @@ -34,5 +38,7 @@ func (u *promUnifi) LogDebugf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "debug"}, }) - u.Collector.LogDebugf(msg, v...) + if u.Collector != nil { + u.Collector.LogDebugf(msg, v...) + } } diff --git a/pkg/webserver/logger.go b/pkg/webserver/logger.go index 31d2baa5..65c8acd3 100644 --- a/pkg/webserver/logger.go +++ b/pkg/webserver/logger.go @@ -12,7 +12,9 @@ func (s *Server) Logf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "info"}, }) - s.Collect.Logf(msg, v...) + if s.Collect != nil { + s.Collect.Logf(msg, v...) + } } // LogErrorf logs an error message. @@ -22,7 +24,9 @@ func (s *Server) LogErrorf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "error"}, }) - s.Collect.LogErrorf(msg, v...) + if s.Collect != nil { + s.Collect.LogErrorf(msg, v...) + } } // LogDebugf logs a debug message. @@ -32,5 +36,7 @@ func (s *Server) LogDebugf(msg string, v ...any) { Msg: fmt.Sprintf(msg, v...), Tags: map[string]string{"type": "debug"}, }) - s.Collect.LogDebugf(msg, v...) + if s.Collect != nil { + s.Collect.LogDebugf(msg, v...) + } } diff --git a/pkg/webserver/server.go b/pkg/webserver/server.go index 9d3be346..5854b90f 100644 --- a/pkg/webserver/server.go +++ b/pkg/webserver/server.go @@ -95,7 +95,7 @@ func (s *Server) Run(c poller.Collect) error { return s.Start() } -func (s *Server) DebugOutput(l poller.Logger) (bool, error) { +func (s *Server) DebugOutput() (bool, error) { if s == nil { return true, nil }