Use a config file instead of env vars.

This commit is contained in:
DN2 2018-04-22 15:39:55 -07:00
parent 74c64be507
commit bb0e3ccfd8
8 changed files with 110 additions and 57 deletions

View File

@ -1,17 +0,0 @@
UNIFI_ADDR="107.170.232.179"
UNIFI_PORT="8443"
# Go to Settings -> Admins and add (or use) a read-only user for this.
UNIFI_USERNAME="username"
UNIFI_PASSWORD="password"
# Can be 1m15s for 1 minute 0 seconds, 15s for 15 seconds, etc.
INTERVAL="15s"
INFLUXDB_ADDR="http://hostname:8086"
INFLUXDB_DATABASE="unifi"
INFLUXDB_USERNAME="unifi"
INFLUXDB_PASSWORD="password"
export UNIFI_ADDR UNIFI_PORT UNIFI_USERNAME UNIFI_PASSWORD
export INTERVAL
export INFLUXDB_ADDR INFLUXDB_DATABASE INFLUXDB_USERNAME INFLUXDB_PASSWORD

2
.gitignore vendored
View File

@ -1,4 +1,4 @@
.env
/up.conf
/unifi-poller
/*.1.gz
/*.1

20
Godeps/Godeps.json generated
View File

@ -21,6 +21,26 @@
"Comment": "v1.5.0-149-g14dcc5d",
"Rev": "14dcc5d6e7a6b15e17aba7b104b8ad0ca6c91ad2"
},
{
"ImportPath": "github.com/naoina/go-stringutil",
"Comment": "v0.1.0",
"Rev": "6b638e95a32d0c1131db0e7fe83775cbea4a0d0b"
},
{
"ImportPath": "github.com/naoina/toml",
"Comment": "v0.1.0",
"Rev": "751171607256bb66e64c9f0220c00662420c38e9"
},
{
"ImportPath": "github.com/naoina/toml/ast",
"Comment": "v0.1.0",
"Rev": "751171607256bb66e64c9f0220c00662420c38e9"
},
{
"ImportPath": "github.com/ogier/pflag",
"Comment": "v0.0.1-7-g45c278a",
"Rev": "45c278ab3607870051a2ea9040bb85fcb8557481"
},
{
"ImportPath": "github.com/pkg/errors",
"Comment": "v0.8.0-6-g2b3a18b",

View File

@ -1,20 +1,12 @@
# Unifi
Collect your Unifi Controller Client data and send it to an InfluxDB instance.
Collect your Unifi Controller Client data and send it to an InfluxDB instance. Grafana dashboard included.
![image](https://raw.githubusercontent.com/davidnewhall/unifi/master/grafana-unifi-dashboard.png)
## Deploying
## Installation
Clone the repository and using `.env.example` create your own `.env` file with your Unifi GUI and InfluxDB credentials.
Set your environment variables before running:
```
source .env ; ./unifi-poller
```
[See the Wiki!](https://github.com/davidnewhall/unifi-poller/wiki/Installation)
## Copyright & License
Copyright © 2016 Garrett Bjerkhoel. See [MIT-LICENSE](http://github.com/dewski/unifi/blob/master/MIT-LICENSE) for details.
Copyright © 2016 Garrett Bjerkhoel. See [MIT-LICENSE](MIT-LICENSE) for details.

View File

@ -5,6 +5,9 @@ import (
"time"
)
// Version will be injected at build time.
var Version = "v0.1"
const (
// LoginPath is Unifi Controller Login API Path
LoginPath = "/api/login"
@ -17,6 +20,7 @@ const (
// UserGroupPath contains usergroup configurations.
UserGroupPath = "/api/s/default/rest/usergroup"
// App defaults in case they're missing from the config.
defaultConfFile = "/usr/local/etc/unifi-poller/up.conf"
defaultInterval = 30 * time.Second
defaultInfxDb = "unifi"
defaultInfxUser = "unifi"
@ -28,13 +32,28 @@ const (
// Config represents the data needed to poll a controller and report to influxdb.
type Config struct {
Interval time.Duration `json:"interval" toml:"interval" xml:"interval" yaml:"interval"`
InfluxURL string `json:"influx_url" toml:"influx_addr" xml:"influx_addr" yaml:"influx_addr"`
InfluxUser string `json:"influx_user" toml:"influx_user" xml:"influx_user" yaml:"influx_user"`
InfluxPass string `json:"influx_pass" toml:"influx_pass" xml:"influx_pass" yaml:"influx_pass"`
InfluxDB string `json:"influx_db" toml:"influx_db" xml:"influx_db" yaml:"influx_db"`
UnifiUser string `json:"unifi_user" toml:"unifi_user" xml:"unifi_user" yaml:"unifi_user"`
UnifiPass string `json:"unifi_pass" toml:"unifi_pass" xml:"unifi_pass" yaml:"unifi_pass"`
UnifiBase string `json:"unifi_url" toml:"unifi_url" xml:"unifi_url" yaml:"unifi_url"`
Interval Dur `json:"interval" toml:"interval" xml:"interval" yaml:"interval"`
InfluxURL string `json:"influx_url" toml:"influx_url" xml:"influx_url" yaml:"influx_url"`
InfluxUser string `json:"influx_user" toml:"influx_user" xml:"influx_user" yaml:"influx_user"`
InfluxPass string `json:"influx_pass" toml:"influx_pass" xml:"influx_pass" yaml:"influx_pass"`
InfluxDB string `json:"influx_db" toml:"influx_db" xml:"influx_db" yaml:"influx_db"`
UnifiUser string `json:"unifi_user" toml:"unifi_user" xml:"unifi_user" yaml:"unifi_user"`
UnifiPass string `json:"unifi_pass" toml:"unifi_pass" xml:"unifi_pass" yaml:"unifi_pass"`
UnifiBase string `json:"unifi_url" toml:"unifi_url" xml:"unifi_url" yaml:"unifi_url"`
uniClient *http.Client
}
// Dur is used to UnmarshalTOML into a time.Duration value.
type Dur struct {
value time.Duration
}
// UnmarshalTOML parses a duration type from a config file.
func (v *Dur) UnmarshalTOML(data []byte) error {
unquoted := string(data[1 : len(data)-1])
dur, err := time.ParseDuration(unquoted)
if err == nil {
v.value = dur
}
return err
}

View File

@ -4,6 +4,7 @@ import (
"bytes"
"crypto/tls"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
@ -12,15 +13,36 @@ import (
"time"
influx "github.com/influxdata/influxdb/client/v2"
"github.com/naoina/toml"
flg "github.com/ogier/pflag"
"github.com/pkg/errors"
)
func main() {
config := GetConfig()
flg.Usage = func() {
fmt.Println("Usage: unifi-poller [--config=filepath] [--debug] [--version]")
flg.PrintDefaults()
}
configFile := flg.StringP("config", "c", defaultConfFile, "Poller Config File (TOML Format)")
debug := flg.BoolP("debug", "D", false, "Turn on the Spam (default false)")
version := flg.BoolP("version", "v", false, "Print the version and exit.")
flg.Parse()
if *version {
fmt.Println("unifi-poller version:", Version)
os.Exit(0) // don't run anything else.
}
if log.SetFlags(0); *debug {
log.SetFlags(log.Lshortfile | log.Lmicroseconds | log.Ldate)
}
config, errc := GetConfig(*configFile)
if errc != nil {
flg.Usage()
log.Fatalln("Config Error:", errc)
}
if err := config.AuthController(); err != nil {
log.Fatal(err)
}
log.Println("Authenticated to Unifi Controller", config.UnifiBase, "as user", config.UnifiUser)
log.Println("Authenticated to Unifi Controller @", config.UnifiBase, "as user", config.UnifiUser)
infdb, err := influx.NewHTTPClient(influx.HTTPConfig{
Addr: config.InfluxURL,
@ -31,28 +53,30 @@ func main() {
log.Fatal(err)
}
log.Println("Logging Unifi Metrics to InfluXDB @", config.InfluxURL, "as user", config.InfluxUser)
log.Println("Polling Unifi Controller, interval:", config.Interval)
log.Println("Polling Unifi Controller, interval:", config.Interval.value)
config.PollUnifiController(infdb)
}
// GetConfig parses and returns our configuration data.
func GetConfig() Config {
// TODO: A real config file.
interval, err := time.ParseDuration(os.Getenv("INTERVAL"))
if err != nil {
log.Println("Invalid Interval, defaulting to", defaultInterval)
interval = time.Duration(defaultInterval)
}
return Config{
InfluxURL: os.Getenv("INFLUXDB_URL"),
InfluxUser: os.Getenv("INFLUXDB_USERNAME"),
InfluxPass: os.Getenv("INFLUXDB_PASSWORD"),
InfluxDB: os.Getenv("INFLUXDB_DATABASE"),
UnifiUser: os.Getenv("UNIFI_USERNAME"),
func GetConfig(configFile string) (Config, error) {
// Preload our defaults.
config := Config{
InfluxURL: defaultInfxURL,
InfluxUser: defaultInfxUser,
InfluxPass: defaultInfxPass,
InfluxDB: defaultInfxDb,
UnifiUser: defaultUnifUser,
UnifiPass: os.Getenv("UNIFI_PASSWORD"),
UnifiBase: "https://" + os.Getenv("UNIFI_ADDR") + ":" + os.Getenv("UNIFI_PORT"),
Interval: interval,
UnifiBase: defaultUnifURL,
Interval: Dur{value: defaultInterval},
}
if buf, err := ioutil.ReadFile(configFile); err != nil {
return config, err
// This is where the defaults in the config variable are overwritten.
} else if err := toml.Unmarshal(buf, &config); err != nil {
return config, errors.Wrap(err, "invalid config")
}
return config, nil
}
// AuthController creates a http.Client with authenticated cookies.
@ -80,7 +104,7 @@ func (c *Config) AuthController() error {
// PollUnifiController runs forever, polling and pushing.
func (c *Config) PollUnifiController(infdb influx.Client) {
ticker := time.NewTicker(c.Interval)
ticker := time.NewTicker(c.Interval.value)
for range ticker.C {
clients, err := c.GetUnifiClients()
if err != nil {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 909 KiB

After

Width:  |  Height:  |  Size: 246 KiB

15
up.conf.example Normal file
View File

@ -0,0 +1,15 @@
# The Unifi Controller only updates traffic stats about every 30 seconds.
# Setting this to something lower may lead to "zeros" in your data. You've been warned.
interval = "30s"
# InfluxDB does not require auth by default, so the user/password are probably unimportant.
influx_url = "http://127.0.0.1:8086"
influx_user = "unifi"
influx_pass = "unifi"
# Be sure to create this database.
influx_db = "unifi"
# Make a read-only user in the Unifi Admin Settings.
unifi_user = "influxdb"
unifi_pass = "4BB9345C-2341-48D7-99F5-E01B583FF77F"
unifi_url = "https://127.0.0.1:8443"