add new interface for testing
This commit is contained in:
parent
a5f858c23a
commit
db9bcd5687
|
|
@ -3,6 +3,7 @@
|
||||||
package datadogunifi
|
package datadogunifi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"reflect"
|
"reflect"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -203,6 +204,22 @@ func (u *DatadogUnifi) Enabled() bool {
|
||||||
return *u.Enable
|
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.
|
// Run runs a ticker to poll the unifi server and update Datadog.
|
||||||
func (u *DatadogUnifi) Run(c poller.Collect) error {
|
func (u *DatadogUnifi) Run(c poller.Collect) error {
|
||||||
u.Collector = c
|
u.Collector = c
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import (
|
||||||
"github.com/unpoller/unifi"
|
"github.com/unpoller/unifi"
|
||||||
"github.com/unpoller/unpoller/pkg/poller"
|
"github.com/unpoller/unpoller/pkg/poller"
|
||||||
"github.com/unpoller/unpoller/pkg/webserver"
|
"github.com/unpoller/unpoller/pkg/webserver"
|
||||||
|
"golang.org/x/net/context"
|
||||||
"golift.io/cnfg"
|
"golift.io/cnfg"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -142,6 +143,51 @@ func (u *InfluxUnifi) Enabled() bool {
|
||||||
return !u.Disable
|
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.
|
// Run runs a ticker to poll the unifi server and update influxdb.
|
||||||
func (u *InfluxUnifi) Run(c poller.Collect) error {
|
func (u *InfluxUnifi) Run(c poller.Collect) error {
|
||||||
u.Collector = c
|
u.Collector = c
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,47 @@ func (u *InputUnifi) Initialize(l poller.Logger) error {
|
||||||
return nil
|
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) {
|
func (u *InputUnifi) logController(c *Controller) {
|
||||||
u.Logf(" => URL: %s (verify SSL: %v)", c.URL, *c.VerifySSL)
|
u.Logf(" => URL: %s (verify SSL: %v)", c.URL, *c.VerifySSL)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,9 @@ func (l *Loki) Logf(msg string, v ...any) {
|
||||||
Msg: fmt.Sprintf(msg, v...),
|
Msg: fmt.Sprintf(msg, v...),
|
||||||
Tags: map[string]string{"type": "info"},
|
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.
|
// LogErrorf logs an error message.
|
||||||
|
|
@ -24,7 +26,9 @@ func (l *Loki) LogErrorf(msg string, v ...any) {
|
||||||
Msg: fmt.Sprintf(msg, v...),
|
Msg: fmt.Sprintf(msg, v...),
|
||||||
Tags: map[string]string{"type": "error"},
|
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.
|
// LogDebugf logs a debug message.
|
||||||
|
|
@ -34,5 +38,7 @@ func (l *Loki) LogDebugf(msg string, v ...any) {
|
||||||
Msg: fmt.Sprintf(msg, v...),
|
Msg: fmt.Sprintf(msg, v...),
|
||||||
Tags: map[string]string{"type": "debug"},
|
Tags: map[string]string{"type": "debug"},
|
||||||
})
|
})
|
||||||
l.Collect.LogDebugf(msg, v...)
|
if l.Collect != nil {
|
||||||
|
l.Collect.LogDebugf(msg, v...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,19 @@ func (l *Loki) Enabled() bool {
|
||||||
return !l.Disable
|
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.
|
// Run is fired from the poller library after the Config is unmarshalled.
|
||||||
func (l *Loki) Run(collect poller.Collect) error {
|
func (l *Loki) Run(collect poller.Collect) error {
|
||||||
l.Collect = collect
|
l.Collect = collect
|
||||||
|
|
@ -85,7 +98,10 @@ func (l *Loki) Run(collect poller.Collect) error {
|
||||||
}
|
}
|
||||||
l.Logf("Loki enabled")
|
l.Logf("Loki enabled")
|
||||||
|
|
||||||
l.ValidateConfig()
|
if err := l.ValidateConfig(); err != nil {
|
||||||
|
l.LogErrorf("invalid loki config")
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
fake := *l.Config
|
fake := *l.Config
|
||||||
fake.Password = strconv.FormatBool(fake.Password != "")
|
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,
|
// ValidateConfig sets initial "last" update time. Also creates an http client,
|
||||||
// makes sure URL is sane, and sets interval within min/max limits.
|
// 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 {
|
if l.Interval.Duration > maxInterval {
|
||||||
l.Interval.Duration = maxInterval
|
l.Interval.Duration = maxInterval
|
||||||
} else if l.Interval.Duration < minInterval {
|
} else if l.Interval.Duration < minInterval {
|
||||||
|
|
@ -110,6 +126,7 @@ func (l *Loki) ValidateConfig() {
|
||||||
pass, err := os.ReadFile(strings.TrimPrefix(l.Password, "file://"))
|
pass, err := os.ReadFile(strings.TrimPrefix(l.Password, "file://"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.LogErrorf("Reading Loki Password File: %v", err)
|
l.LogErrorf("Reading Loki Password File: %v", err)
|
||||||
|
return fmt.Errorf("error reading password file")
|
||||||
}
|
}
|
||||||
|
|
||||||
l.Password = strings.TrimSpace(string(pass))
|
l.Password = strings.TrimSpace(string(pass))
|
||||||
|
|
@ -118,6 +135,7 @@ func (l *Loki) ValidateConfig() {
|
||||||
l.last = time.Now().Add(-l.Interval.Duration)
|
l.last = time.Now().Add(-l.Interval.Duration)
|
||||||
l.client = l.httpClient()
|
l.client = l.httpClient()
|
||||||
l.URL = strings.TrimRight(l.URL, "/") // gets a path appended to it later.
|
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.
|
// PollController runs forever, polling UniFi for events and pushing them to Loki.
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@ func (r *Report) IDS(event *unifi.IDS, logs *Logs) {
|
||||||
}
|
}
|
||||||
|
|
||||||
r.Counts[typeIDS]++ // increase counter and append new log line.
|
r.Counts[typeIDS]++ // increase counter and append new log line.
|
||||||
|
|
||||||
logs.Streams = append(logs.Streams, LogStream{
|
logs.Streams = append(logs.Streams, LogStream{
|
||||||
Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), event.Msg}},
|
Entries: [][]string{{strconv.FormatInt(event.Datetime.UnixNano(), 10), event.Msg}},
|
||||||
Labels: CleanLabels(map[string]string{
|
Labels: CleanLabels(map[string]string{
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,19 @@ func (p *plugin) Enabled() bool {
|
||||||
return !p.Disable
|
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.
|
// 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.
|
// In other words, don't run your code in a go routine, it already is.
|
||||||
func (p *plugin) Run(c poller.Collect) error {
|
func (p *plugin) Run(c poller.Collect) error {
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ type Input interface {
|
||||||
Metrics(*Filter) (*Metrics, error) // Called every time new metrics are requested.
|
Metrics(*Filter) (*Metrics, error) // Called every time new metrics are requested.
|
||||||
Events(*Filter) (*Events, error) // This is new.
|
Events(*Filter) (*Events, error) // This is new.
|
||||||
RawMetrics(*Filter) ([]byte, error)
|
RawMetrics(*Filter) ([]byte, error)
|
||||||
|
DebugInputs(Logger) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// InputPlugin describes an input plugin's consumable interface.
|
// InputPlugin describes an input plugin's consumable interface.
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,7 @@ type Collect interface {
|
||||||
type OutputPlugin interface {
|
type OutputPlugin interface {
|
||||||
Run(Collect) error
|
Run(Collect) error
|
||||||
Enabled() bool
|
Enabled() bool
|
||||||
|
DebugOutput(Logger) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Output defines the output data for a metric exporter like influx or prometheus.
|
// Output defines the output data for a metric exporter like influx or prometheus.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,9 @@ package promunifi
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"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 {
|
func (u *promUnifi) Enabled() bool {
|
||||||
if u == nil {
|
if u == nil {
|
||||||
return false
|
return false
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ package webserver
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
@ -94,6 +95,32 @@ func (s *Server) Run(c poller.Collect) error {
|
||||||
return s.Start()
|
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.
|
// Start gets the web server going.
|
||||||
func (s *Server) Start() (err error) {
|
func (s *Server) Start() (err error) {
|
||||||
s.server = &http.Server{
|
s.server = &http.Server{
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue