Merge branch 'master' of ../mysqlunifi into merge-them-all

This commit is contained in:
Cody Lee 2022-11-23 21:14:48 -06:00
commit 1480ac947f
No known key found for this signature in database
8 changed files with 209 additions and 0 deletions

3
integrations/mysqlunifi/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/mysqlunifi
/*.so
/go.sum

View File

@ -0,0 +1,9 @@
language: go
go:
- 1.15.x
before_install:
# download super-linter: golangci-lint
- curl -sL https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(go env GOPATH)/bin latest
script:
- golangci-lint run --enable-all -D gochecknoinits,exhaustivestruct,nlreturn,forbidigo,goerr113
- go test ./...

View File

@ -0,0 +1,21 @@
MIT LICENSE.
Copyright (c) 2018-2020 David Newhall II
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,28 @@
# MYSQL Output Plugin Example
This plugin is not finished and did not get finished for the release of poller v2.
Sorry about that. I'll try to get it working soon! 2/4/20
The code here, and the dynamic plugin provided shows an example of how you can
write your own output for unifi-poller. This plugin records some very basic
data about clients on a unifi network into a mysql database.
You could write outputs that do... anything. An example: They could compare current
connected clients to a previous list (in a db, or stored in memory), and send a
notification if it changes. The possibilities are endless.
You must compile your plugin using the unifi-poller source for the version you're
using. In other words, to build a plugin for version 2.0.1, do this:
```
mkdir -p $GOPATH/src/github.com/unifi-poller
cd $GOPATH/src/github.com/unifi-poller
git clone git@github.com:unifi-poller/unifi-poller.git
cd unifi-poller
git checkout v2.0.1
cp -r <your plugin> plugins/
GOOS=linux make plugins
```
The plugin you copy in *must* have a `main.go` file for `make plugins` to build it.

View File

@ -0,0 +1,9 @@
package main
/* Everything in this file runs after the config is unmarshalled and we've
verified the configuration for the poller. */
func (p *plugin) runCollector() error {
p.Logf("mysql plugin is not finished")
return nil
}

View File

@ -0,0 +1,8 @@
module github.com/unifi-poller/mysqlunifi
go 1.15
require (
github.com/unifi-poller/poller v0.0.0-20210315075554-47d92433b172
golift.io/cnfg v0.0.7
)

View File

@ -0,0 +1,97 @@
package main
import (
"fmt"
"github.com/unifi-poller/poller"
"golift.io/cnfg"
)
// Only capital (exported) members are unmarshaled when passed into poller.NewOutput().
type plugin struct {
*Config `json:"mysql" toml:"mysql" xml:"mysql" yaml:"mysql"`
poller.Collect
}
// Config represents the data that is unmarshalled from the up.conf config file for this plugins.
// See up.conf.example.mysql for sample input data.
type Config struct {
Disable bool `json:"disable" toml:"disable" xml:"disable" yaml:"disable"`
Interval cnfg.Duration `json:"interval" toml:"interval" xml:"interval" yaml:"interval"`
Host string `json:"host" toml:"host" xml:"host" yaml:"host"`
User string `json:"user" toml:"user" xml:"user" yaml:"user"`
Pass string `json:"pass" toml:"pass" xml:"pass" yaml:"pass"`
DB string `json:"db" toml:"db" xml:"db" yaml:"db"`
Devices []Device `json:"devices" toml:"devices" xml:"device" yaml:"devices"`
Clients *Clients `json:"clients" toml:"clients" xml:"clients" yaml:"clients"`
}
// Device represents the configuration to save a devices' data.
// Type is one of uap, usw, ugw, udm.
// Table represents the mysql table name we save these fields to.
// Fields is a map of api response data key -> mysql column.
type Device struct {
Type string `json:"type" toml:"type" xml:"type" yaml:"type"`
Table string `json:"table" toml:"table" xml:"table" yaml:"table"`
Fields map[string]string `json:"fields" toml:"fields" xml:"field" yaml:"fields"`
}
// Clients represents the configuration to save clients' data.
// Table represents the mysql table name we save these fields to.
// Fields is a map of api response data key -> mysql column.
type Clients struct {
Table string `json:"table" toml:"table" xml:"table" yaml:"table"`
Fields map[string]string `json:"fields" toml:"fields" xml:"field" yaml:"fields"`
}
func init() {
u := &plugin{Config: &Config{}}
poller.NewOutput(&poller.Output{
Name: "mysql",
Config: u, // pass in the struct *above* your config (so it can see the struct tags).
Method: u.Run,
})
}
// 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 {
if p.Collect = c; c == nil || p.Config == nil || p.Disable {
return nil // no config or disabled, bail out.
}
if err := p.validateConfig(); err != nil {
return err
}
return p.runCollector()
}
// validateConfig checks input sanity.
func (p *plugin) validateConfig() error {
if p.Interval.Duration == 0 {
return fmt.Errorf("must provide a polling interval")
}
if p.Clients == nil && len(p.Devices) == 0 {
return fmt.Errorf("must configure client or device collection; both empty")
}
for _, d := range p.Devices {
if len(d.Fields) == 0 {
return fmt.Errorf("no fields defined for device type %s, table %s", d.Type, d.Table)
}
}
if p.Clients != nil && p.Clients.Fields == nil {
return fmt.Errorf("no fields defined for clients; if you don't want to store client data, remove it from the config")
}
return nil
}
// main() is required, but it shouldn't do much as it's not used in plugin mode.
func main() {
fmt.Println("this is a unifi-poller plugin; not an application")
}

View File

@ -0,0 +1,34 @@
[poller]
debug = true
plugins = ["/path/to/mysql.so"]
[mysql]
interval = "30s"
host = "127.0.0.1:3306"
user = "unifipoller"
pass = "unifipoller"
db = "unifipoller"
[mysql.clients]
table = "client_records"
[mysql.clients.fields]
tx_bytes = "tx-bytes"
rx_bytes = "rx-bytes"
[[mysql.devices]]
type = "uap"
table = "uap_records"
[mysql.devices.fields]
tx_bytes = "tx-bytes"
rx_bytes = "rx-bytes"
[[mysql.devices]]
type = "ugw"
table = "usg_records"
[mysql.devices.fields]
wan_bytes = "wan_bytes"
[unifi.defaults]
url = "https://127.0.0.1:8443"
user = "unifipoller"
pass = "4BB9345C-2341-48D7-99F5-E01B583FF77F"