package inputunifi /* This file contains the three poller.Input interface methods. */ import ( "fmt" "os" "strings" "github.com/pkg/errors" "github.com/unifi-poller/poller" "github.com/unifi-poller/unifi" ) var ( errDynamicLookupsDisabled = fmt.Errorf("filter path requested but dynamic lookups disabled") errControllerNumNotFound = fmt.Errorf("controller number not found") errNoFilterKindProvided = fmt.Errorf("must provide filter: devices, clients, other") ) // Initialize gets called one time when starting up. // Satisfies poller.Input interface. func (u *InputUnifi) Initialize(l poller.Logger) error { if u.Config == nil { u.Config = &Config{Disable: true} } if u.Disable { l.Logf("UniFi input plugin disabled or missing configuration!") return nil } if u.setDefaults(&u.Default); len(u.Controllers) == 0 && !u.Dynamic { u.Controllers = []*Controller{&u.Default} } if len(u.Controllers) == 0 { l.Logf("No controllers configured. Polling dynamic controllers only!") } u.dynamic = make(map[string]*Controller) u.Logger = l for i, c := range u.Controllers { switch err := u.getUnifi(u.setControllerDefaults(c)); err { case nil: if err := u.checkSites(c); err != nil { u.LogErrorf("checking sites on %s: %v", c.Role, err) } u.Logf("Configured UniFi Controller %d:", i+1) u.Logf(" => Version: %s", c.Unifi.ServerVersion) default: u.LogErrorf("Controller %d Auth or Connection failed, but continuing to retry! %v", i, err) } u.Logf(" => URL: %s", c.URL) u.Logf(" => Username: %s (has password: %v)", c.User, c.Pass != "") u.Logf(" => Role: %s", c.Role) u.Logf(" => Hash PII: %v", *c.HashPII) u.Logf(" => Verify SSL: %v", *c.VerifySSL) u.Logf(" => Save DPI: %v", *c.SaveDPI) u.Logf(" => Save IDS: %v", *c.SaveIDS) u.Logf(" => Save Sites: %v", *c.SaveSites) } return nil } // Metrics grabs all the measurements from a UniFi controller and returns them. func (u *InputUnifi) Metrics() (*poller.Metrics, bool, error) { return u.MetricsFrom(nil) } // MetricsFrom grabs all the measurements from a UniFi controller and returns them. func (u *InputUnifi) MetricsFrom(filter *poller.Filter) (*poller.Metrics, bool, error) { if u.Disable { return nil, false, nil } errs := []string{} metrics := &poller.Metrics{} ok := false if filter != nil && filter.Path != "" { if !u.Dynamic { return metrics, false, errDynamicLookupsDisabled } // Attempt a dynamic metrics fetch from an unconfigured controller. m, err := u.dynamicController(filter.Path) return m, err == nil && m != nil, err } // Check if the request is for an existing, configured controller. for _, c := range u.Controllers { if filter != nil && !strings.EqualFold(c.Role, filter.Role) { continue } m, err := u.collectController(c) if err != nil { errs = append(errs, err.Error()) } if m == nil { continue } ok = true metrics = poller.AppendMetrics(metrics, m) } if len(errs) > 0 { return metrics, ok, fmt.Errorf(strings.Join(errs, ", ")) // nolint: goerr113 } return metrics, ok, nil } // RawMetrics returns API output from the first configured unifi controller. func (u *InputUnifi) RawMetrics(filter *poller.Filter) ([]byte, error) { if l := len(u.Controllers); filter.Unit >= l { return nil, errors.Wrapf(errControllerNumNotFound, "%d controller(s) configured, '%d'", l, filter.Unit) } c := u.Controllers[filter.Unit] if u.isNill(c) { u.Logf("Re-authenticating to UniFi Controller: %s", c.URL) if err := u.getUnifi(c); err != nil { return nil, errors.Wrapf(err, "re-authenticating to %s", c.Role) } } if err := u.checkSites(c); err != nil { return nil, err } sites, err := u.getFilteredSites(c) if err != nil { return nil, err } switch filter.Kind { case "d", "device", "devices": return u.dumpSitesJSON(c, unifi.APIDevicePath, "Devices", sites) case "client", "clients", "c": return u.dumpSitesJSON(c, unifi.APIClientPath, "Clients", sites) case "other", "o": _, _ = fmt.Fprintf(os.Stderr, "[INFO] Dumping Path '%s':\n", filter.Path) return c.Unifi.GetJSON(filter.Path) default: return []byte{}, errNoFilterKindProvided } }