add new interface for testing
This commit is contained in:
		
							parent
							
								
									a5f858c23a
								
							
						
					
					
						commit
						db9bcd5687
					
				|  | @ -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 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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) | ||||
| 
 | ||||
|  |  | |||
|  | @ -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...) | ||||
| 	} | ||||
| } | ||||
|  |  | |||
|  | @ -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.
 | ||||
|  |  | |||
|  | @ -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 { | ||||
|  |  | |||
|  | @ -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.
 | ||||
|  |  | |||
|  | @ -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.
 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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{ | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue