switch to dep, another test, add flags - minor features
This commit is contained in:
parent
424b060839
commit
bd8c11ed50
|
|
@ -1,75 +0,0 @@
|
|||
{
|
||||
"ImportPath": "github.com/davidnewhall/unifi-poller",
|
||||
"GoVersion": "go1.11",
|
||||
"GodepVersion": "v79",
|
||||
"Packages": [
|
||||
"./..."
|
||||
],
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "github.com/davecgh/go-spew/spew",
|
||||
"Comment": "v1.1.0",
|
||||
"Rev": "346938d642f2ec3594ed81d874461961cd0faa76"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/influxdata/influxdb/client/v2",
|
||||
"Comment": "v1.5.0-149-g14dcc5d6e",
|
||||
"Rev": "14dcc5d6e7a6b15e17aba7b104b8ad0ca6c91ad2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/influxdata/influxdb/models",
|
||||
"Comment": "v1.5.0-149-g14dcc5d6e",
|
||||
"Rev": "14dcc5d6e7a6b15e17aba7b104b8ad0ca6c91ad2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/influxdata/influxdb/pkg/escape",
|
||||
"Comment": "v1.5.0-149-g14dcc5d6e",
|
||||
"Rev": "14dcc5d6e7a6b15e17aba7b104b8ad0ca6c91ad2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/naoina/go-stringutil",
|
||||
"Comment": "v0.1.0",
|
||||
"Rev": "6b638e95a32d0c1131db0e7fe83775cbea4a0d0b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/naoina/toml",
|
||||
"Comment": "v0.1.1-2-g9fafd69",
|
||||
"Rev": "9fafd69674167c06933b1787ae235618431ce87f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/naoina/toml/ast",
|
||||
"Comment": "v0.1.1-2-g9fafd69",
|
||||
"Rev": "9fafd69674167c06933b1787ae235618431ce87f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/ogier/pflag",
|
||||
"Comment": "v0.0.1-7-g45c278a",
|
||||
"Rev": "45c278ab3607870051a2ea9040bb85fcb8557481"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/pkg/errors",
|
||||
"Comment": "v0.8.0-6-g2b3a18b",
|
||||
"Rev": "2b3a18b5f0fb6b4f9190549597d3f962c02bc5eb"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/pmezard/go-difflib/difflib",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stretchr/testify/assert",
|
||||
"Comment": "v1.1.4-27-g4d4bfba",
|
||||
"Rev": "4d4bfba8f1d1027c4fdbe371823030df51419987"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stretchr/testify/vendor/github.com/davecgh/go-spew/spew",
|
||||
"Comment": "v1.1.4-27-g4d4bfba",
|
||||
"Rev": "4d4bfba8f1d1027c4fdbe371823030df51419987"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/stretchr/testify/vendor/github.com/pmezard/go-difflib/difflib",
|
||||
"Comment": "v1.1.4-27-g4d4bfba",
|
||||
"Rev": "4d4bfba8f1d1027c4fdbe371823030df51419987"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1,5 +0,0 @@
|
|||
This directory tree is generated automatically by godep.
|
||||
|
||||
Please do not edit.
|
||||
|
||||
See https://github.com/tools/godep for more information.
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
|
||||
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/davecgh/go-spew"
|
||||
packages = ["spew"]
|
||||
revision = "8991bc29aa16c548c550c7ff78260e27b9ab7c73"
|
||||
version = "v1.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/influxdata/influxdb"
|
||||
packages = [
|
||||
"client/v2",
|
||||
"models",
|
||||
"pkg/escape"
|
||||
]
|
||||
revision = "76f907b0fada2f16931e37471da695349fcdf8c6"
|
||||
version = "v1.7.2"
|
||||
|
||||
[[projects]]
|
||||
branch = "master"
|
||||
name = "github.com/influxdata/platform"
|
||||
packages = [
|
||||
"models",
|
||||
"pkg/escape"
|
||||
]
|
||||
revision = "98469bf07613ffae6f025893761c1e7a5e96e4aa"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/naoina/go-stringutil"
|
||||
packages = ["."]
|
||||
revision = "6b638e95a32d0c1131db0e7fe83775cbea4a0d0b"
|
||||
version = "v0.1.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/naoina/toml"
|
||||
packages = [
|
||||
".",
|
||||
"ast"
|
||||
]
|
||||
revision = "e6f5723bf2a66af014955e0888881314cf294129"
|
||||
version = "v0.1.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/ogier/pflag"
|
||||
packages = ["."]
|
||||
revision = "32a05c62658bd1d7c7e75cbc8195de5d585fde0f"
|
||||
version = "v0.0.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pkg/errors"
|
||||
packages = ["."]
|
||||
revision = "ba968bfe8b2f7e042a574c888954fccecfa385b4"
|
||||
version = "v0.8.1"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/pmezard/go-difflib"
|
||||
packages = ["difflib"]
|
||||
revision = "792786c7400a136282c1664665ae0a8db921c6c2"
|
||||
version = "v1.0.0"
|
||||
|
||||
[[projects]]
|
||||
name = "github.com/stretchr/testify"
|
||||
packages = ["assert"]
|
||||
revision = "ffdc059bfe9ce6a4e144ba849dbedead332c6053"
|
||||
version = "v1.3.0"
|
||||
|
||||
[solve-meta]
|
||||
analyzer-name = "dep"
|
||||
analyzer-version = 1
|
||||
inputs-digest = "3b1d8ae8346fc10f0725163478eab3fa466a2064f4d44077102c5f7651625dc4"
|
||||
solver-name = "gps-cdcl"
|
||||
solver-version = 1
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
# Gopkg.toml example
|
||||
#
|
||||
# Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
|
||||
# for detailed Gopkg.toml documentation.
|
||||
#
|
||||
# required = ["github.com/user/thing/cmd/thing"]
|
||||
# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project"
|
||||
# version = "1.0.0"
|
||||
#
|
||||
# [[constraint]]
|
||||
# name = "github.com/user/project2"
|
||||
# branch = "dev"
|
||||
# source = "github.com/myfork/project2"
|
||||
#
|
||||
# [[override]]
|
||||
# name = "github.com/x/y"
|
||||
# version = "2.4.0"
|
||||
#
|
||||
# [prune]
|
||||
# non-go = false
|
||||
# go-tests = true
|
||||
# unused-packages = true
|
||||
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/influxdata/influxdb"
|
||||
version = "1.7.2"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/naoina/toml"
|
||||
version = "0.1.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/ogier/pflag"
|
||||
version = "0.0.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/pkg/errors"
|
||||
version = "0.8.1"
|
||||
|
||||
[[constraint]]
|
||||
name = "github.com/stretchr/testify"
|
||||
version = "1.3.0"
|
||||
|
||||
[prune]
|
||||
go-tests = true
|
||||
unused-packages = true
|
||||
|
|
@ -43,6 +43,4 @@ man:
|
|||
script/build_manpages.sh ./
|
||||
|
||||
deps:
|
||||
rm -rf Godeps vendor
|
||||
godep save ./...
|
||||
godep update ./...
|
||||
dep ensure -update
|
||||
|
|
|
|||
|
|
@ -12,11 +12,22 @@ unifi-poller(1) -- Utility to poll Unifi Metrics and drop them into InfluxDB
|
|||
|
||||
## OPTIONS
|
||||
|
||||
`unifi-poller [-c <config file>] [-h] [-v]`
|
||||
`unifi-poller [-c <config file>] [-D] [-q] [-s] [-h] [-v]`
|
||||
|
||||
-c, --config <file_path>
|
||||
Provide a configuration file (instead of the default).
|
||||
|
||||
-D, --debug
|
||||
Turns on line numbers, microsecond logging, and a per-device log.
|
||||
|
||||
-q, --quiet
|
||||
Turns off per-device log and per-interval log. Logs only errors.
|
||||
Recommend using -D with this setting for better error logging.
|
||||
|
||||
-s, --verify-ssl
|
||||
If your Unifi controller has a valid SSL certificate, you can enable
|
||||
this option to validate it. Otherwise, any SSL certificate is valid.
|
||||
|
||||
-v, --version
|
||||
Display version and exit.
|
||||
|
||||
|
|
|
|||
|
|
@ -21,12 +21,15 @@ func main() {
|
|||
}
|
||||
configFile := flg.StringP("config", "c", defaultConfFile, "Poller Config File (TOML Format)")
|
||||
flg.BoolVarP(&unidev.Debug, "debug", "D", false, "Turn on the Spam (default false)")
|
||||
version := flg.BoolP("version", "v", false, "Print the version and exit.")
|
||||
quiet := flg.BoolP("quiet", "q", false, "Do not print logs on every poll, only errors")
|
||||
version := flg.BoolP("version", "v", false, "Print the version and exit")
|
||||
verifySSL := flg.BoolP("verify-ssl", "s", false, "If your controller has a valid SSL cert, require it with this flag")
|
||||
|
||||
if flg.Parse(); *version {
|
||||
fmt.Println("unifi-poller version:", Version)
|
||||
os.Exit(0) // don't run anything else.
|
||||
}
|
||||
log.Println("Unifi-Poller Starting Up! PID:", os.Getpid())
|
||||
if log.SetFlags(0); unidev.Debug {
|
||||
log.SetFlags(log.Lshortfile | log.Lmicroseconds | log.Ldate)
|
||||
log.Println("Debug Logging Enabled")
|
||||
|
|
@ -38,12 +41,13 @@ func main() {
|
|||
}
|
||||
log.Println("Loaded Configuration:", *configFile)
|
||||
// Create an authenticated session to the Unifi Controller.
|
||||
unifi, err := unidev.AuthController(config.UnifiUser, config.UnifiPass, config.UnifiBase)
|
||||
unifi, err := unidev.AuthController(config.UnifiUser, config.UnifiPass, config.UnifiBase, *verifySSL)
|
||||
if err != nil {
|
||||
log.Fatalln("Unifi Controller Error:", err)
|
||||
}
|
||||
log.Println("Authenticated to Unifi Controller @", config.UnifiBase, "as user", config.UnifiUser)
|
||||
|
||||
if !*quiet {
|
||||
log.Println("Authenticated to Unifi Controller @", config.UnifiBase, "as user", config.UnifiUser)
|
||||
}
|
||||
infdb, err := influx.NewHTTPClient(influx.HTTPConfig{
|
||||
Addr: config.InfluxURL,
|
||||
Username: config.InfluxUser,
|
||||
|
|
@ -52,9 +56,15 @@ func main() {
|
|||
if err != nil {
|
||||
log.Fatalln("InfluxDB Error:", err)
|
||||
}
|
||||
log.Println("Logging Unifi Metrics to InfluXDB @", config.InfluxURL, "as user", config.InfluxUser)
|
||||
log.Println("Polling Unifi Controller, interval:", config.Interval.value)
|
||||
config.PollUnifiController(infdb, unifi)
|
||||
if *quiet {
|
||||
// Do it this way allows debug error logs (line numbers, etc)
|
||||
unidev.Debug = false
|
||||
} else {
|
||||
log.Println("Logging Unifi Metrics to InfluXDB @", config.InfluxURL, "as user", config.InfluxUser)
|
||||
log.Println("Polling Unifi Controller, interval:", config.Interval.value)
|
||||
}
|
||||
log.Println("Everyting checks out! Beginning Poller Routine.")
|
||||
config.PollUnifiController(infdb, unifi, *quiet)
|
||||
}
|
||||
|
||||
// GetConfig parses and returns our configuration data.
|
||||
|
|
@ -80,7 +90,7 @@ func GetConfig(configFile string) (Config, error) {
|
|||
}
|
||||
|
||||
// PollUnifiController runs forever, polling and pushing.
|
||||
func (c *Config) PollUnifiController(infdb influx.Client, unifi *unidev.AuthedReq) {
|
||||
func (c *Config) PollUnifiController(infdb influx.Client, unifi *unidev.AuthedReq, quiet bool) {
|
||||
ticker := time.NewTicker(c.Interval.value)
|
||||
for range ticker.C {
|
||||
var clients, devices []unidev.Asset
|
||||
|
|
@ -107,6 +117,8 @@ func (c *Config) PollUnifiController(infdb influx.Client, unifi *unidev.AuthedRe
|
|||
log.Println("ERROR infdb.Write(bp):", err)
|
||||
continue
|
||||
}
|
||||
log.Println("Logged client state. Clients:", len(clients), "- Devices:", len(devices))
|
||||
if !quiet {
|
||||
log.Println("Logged client state. Clients:", len(clients), "- Devices:", len(devices))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,23 +61,23 @@ func (f *FlexInt) UnmarshalJSON(b []byte) error {
|
|||
|
||||
// AuthController creates a http.Client with authenticated cookies.
|
||||
// Used to make additional, authenticated requests to the APIs.
|
||||
func AuthController(user, pass, url string) (*AuthedReq, error) {
|
||||
func AuthController(user, pass, url string, verifySSL bool) (*AuthedReq, error) {
|
||||
json := `{"username": "` + user + `","password": "` + pass + `"}`
|
||||
jar, err := cookiejar.New(nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cookiejar.New(nil)")
|
||||
}
|
||||
authReq := &AuthedReq{&http.Client{
|
||||
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}},
|
||||
a := &AuthedReq{&http.Client{
|
||||
Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: !verifySSL}},
|
||||
Jar: jar,
|
||||
}, url}
|
||||
req, err := authReq.UniReq(LoginPath, json)
|
||||
req, err := a.UniReq(LoginPath, json)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "UniReq(LoginPath, json)")
|
||||
return a, errors.Wrap(err, "UniReq(LoginPath, json)")
|
||||
}
|
||||
resp, err := authReq.Do(req)
|
||||
resp, err := a.Do(req)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "authReq.Do(req)")
|
||||
return a, errors.Wrap(err, "authReq.Do(req)")
|
||||
}
|
||||
defer func() {
|
||||
if err := resp.Body.Close(); err != nil {
|
||||
|
|
@ -85,18 +85,18 @@ func AuthController(user, pass, url string) (*AuthedReq, error) {
|
|||
}
|
||||
}()
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
return nil, errors.Errorf("authentication failed (%v): %v (status: %v/%v)",
|
||||
return a, errors.Errorf("authentication failed (%v): %v (status: %v/%v)",
|
||||
user, url+LoginPath, resp.StatusCode, resp.Status)
|
||||
}
|
||||
return authReq, nil
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// UniReq is a small helper function that adds an Accept header.
|
||||
func (c AuthedReq) UniReq(apiURL string, params string) (req *http.Request, err error) {
|
||||
func (a AuthedReq) UniReq(apiPath string, params string) (req *http.Request, err error) {
|
||||
if params != "" {
|
||||
req, err = http.NewRequest("POST", c.baseURL+apiURL, bytes.NewBufferString(params))
|
||||
req, err = http.NewRequest("POST", a.baseURL+apiPath, bytes.NewBufferString(params))
|
||||
} else {
|
||||
req, err = http.NewRequest("GET", c.baseURL+apiURL, nil)
|
||||
req, err = http.NewRequest("GET", a.baseURL+apiPath, nil)
|
||||
}
|
||||
if err == nil {
|
||||
req.Header.Add("Accept", "application/json")
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ package unidev
|
|||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
|
|
@ -11,13 +13,15 @@ func TestFlexInt(t *testing.T) {
|
|||
t.Parallel()
|
||||
a := assert.New(t)
|
||||
type testReply struct {
|
||||
Five FlexInt `json:"five"`
|
||||
Seven FlexInt `json:"seven"`
|
||||
Auto FlexInt `json:"auto"`
|
||||
Five FlexInt `json:"five"`
|
||||
Seven FlexInt `json:"seven"`
|
||||
Auto FlexInt `json:"auto"`
|
||||
Channel FlexInt `json:"channel"`
|
||||
}
|
||||
var r testReply
|
||||
// test unmarshalling the custom type three times with different values.
|
||||
a.Nil(json.Unmarshal([]byte(`{"five": "5", "seven": 7, "auto": "auto"}`), &r))
|
||||
|
||||
// test number in string.
|
||||
a.EqualValues(5, r.Five.Number)
|
||||
a.EqualValues("5", r.Five.String)
|
||||
|
|
@ -25,8 +29,54 @@ func TestFlexInt(t *testing.T) {
|
|||
a.EqualValues(7, r.Seven.Number)
|
||||
a.EqualValues("7", r.Seven.String)
|
||||
// test string.
|
||||
a.Nil(json.Unmarshal([]byte(`{"channel": "auto"}`), &r),
|
||||
"a regular string must not produce an unmarshal error")
|
||||
a.EqualValues(0, r.Auto.Number)
|
||||
a.EqualValues("auto", r.Auto.String)
|
||||
// test (error) struct.
|
||||
a.NotNil(json.Unmarshal([]byte(`{"channel": {}}`), &r),
|
||||
"a non-string and non-number must produce an error.")
|
||||
a.EqualValues(0, r.Channel.Number)
|
||||
}
|
||||
|
||||
func TestUniReq(t *testing.T) {
|
||||
t.Parallel()
|
||||
a := assert.New(t)
|
||||
u := "/test/path"
|
||||
url := "http://some.url:8443"
|
||||
// Test empty parameters.
|
||||
authReq := &AuthedReq{&http.Client{}, url}
|
||||
r, err := authReq.UniReq(u, "")
|
||||
a.Nil(err, "newrequest must not produce an error")
|
||||
a.EqualValues(u, r.URL.Path,
|
||||
"the provided apiPath was not added to http request")
|
||||
a.EqualValues(url, r.URL.Scheme+"://"+r.URL.Host, "URL improperly encoded")
|
||||
a.EqualValues("GET", r.Method, "without parameters the method must be GET")
|
||||
a.EqualValues("application/json", r.Header.Get("Accept"), "Accept header must be set to application/json")
|
||||
|
||||
// Test with parameters
|
||||
p := "key1=value9&key2=value7"
|
||||
authReq = &AuthedReq{&http.Client{}, "http://some.url:8443"}
|
||||
r, err = authReq.UniReq(u, p)
|
||||
a.Nil(err, "newrequest must not produce an error")
|
||||
a.EqualValues(u, r.URL.Path,
|
||||
"the provided apiPath was not added to http request")
|
||||
a.EqualValues(url, r.URL.Scheme+"://"+r.URL.Host, "URL improperly encoded")
|
||||
a.EqualValues("POST", r.Method, "with parameters the method must be POST")
|
||||
a.EqualValues("application/json", r.Header.Get("Accept"), "Accept header must be set to application/json")
|
||||
// Check the parameters.
|
||||
d, err := ioutil.ReadAll(r.Body)
|
||||
a.Nil(err, "problem reading request body, POST parameters may be malformed")
|
||||
a.EqualValues(p, string(d), "POST parameters improperly encoded")
|
||||
}
|
||||
|
||||
func TestAuthController(t *testing.T) {
|
||||
t.Parallel()
|
||||
a := assert.New(t)
|
||||
url := "http://127.0.0.1:64431"
|
||||
authReq, err := AuthController("user1", "pass2", url, false)
|
||||
a.NotNil(err)
|
||||
a.EqualValues(url, authReq.baseURL)
|
||||
a.Contains(err.Error(), "authReq.Do(req):", "an invalid destination should product a .Do(req) error.")
|
||||
/* TODO: OPEN web server, check parameters posted, more. This test is incomplete.
|
||||
a.EqualValues(`{"username": "user1","password": "pass2"}`, string(post_params), "user/pass json parameters improperly encoded")
|
||||
*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,8 @@
|
|||
# The Unifi Controller only updates traffic stats about every 30 seconds.
|
||||
# unifi-poller primary configuration file. #
|
||||
# copy this file to: /usr/local/etc/unifi-poller/up.conf #
|
||||
##########################################################
|
||||
|
||||
# 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"
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue