mirror of
https://github.com/nshttpd/mikrotik-exporter.git
synced 2024-11-15 10:15:18 +01:00
Added support to auto discovery with SRV DNS registry (#60)
* Added support to auto discovery witih SRV The yaml configuration has been modified to suport srv parameters. Now the name is taken form the router identity to allow dynamic discovery of devices based on SRV registry. * Corrected format * feat(collector): Added support to use custom DNS * feat(collector): get default dns server from resolv.conf * Remove getIdentity on the static config devices
This commit is contained in:
parent
75b5f8be36
commit
d723fdfe38
18
README.md
18
README.md
@ -53,6 +53,19 @@ devices:
|
||||
port: 8999
|
||||
user: prometheus2
|
||||
password: password_to_second_router
|
||||
- name: routers_srv_dns
|
||||
srv:
|
||||
record: _mikrotik._udp.example.com
|
||||
user: prometheus
|
||||
password: password_to_all_dns_routers
|
||||
- name: routers_srv_custom_dns
|
||||
srv:
|
||||
record: _mikrotik2._udp.example.com
|
||||
dns:
|
||||
address: 1.1.1.1
|
||||
port: 53
|
||||
user: prometheus
|
||||
password: password_to_all_dns_routers
|
||||
|
||||
features:
|
||||
bgp: true
|
||||
@ -64,6 +77,11 @@ features:
|
||||
optics: true
|
||||
```
|
||||
|
||||
If you add a devices with the `srv` parameter instead of `address` the exporter will perform a DNS query
|
||||
to obtain the SRV record and discover the devices dynamically. Also, you can specify a DNS server to use
|
||||
on the query.
|
||||
|
||||
|
||||
###### example output
|
||||
|
||||
```
|
||||
|
@ -8,11 +8,15 @@ import (
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"mikrotik-exporter/config"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
log "github.com/sirupsen/logrus"
|
||||
routeros "gopkg.in/routeros.v2"
|
||||
@ -22,6 +26,7 @@ const (
|
||||
namespace = "mikrotik"
|
||||
apiPort = "8728"
|
||||
apiPortTLS = "8729"
|
||||
dnsPort = 53
|
||||
|
||||
// DefaultTimeout defines the default timeout when connecting to a router
|
||||
DefaultTimeout = 5 * time.Second
|
||||
@ -194,9 +199,52 @@ func (c *collector) Describe(ch chan<- *prometheus.Desc) {
|
||||
// Collect implements the prometheus.Collector interface.
|
||||
func (c *collector) Collect(ch chan<- prometheus.Metric) {
|
||||
wg := sync.WaitGroup{}
|
||||
wg.Add(len(c.devices))
|
||||
|
||||
var realDevices []config.Device
|
||||
|
||||
for _, dev := range c.devices {
|
||||
if (config.SrvRecord{}) != dev.Srv {
|
||||
log.WithFields(log.Fields{
|
||||
"SRV": dev.Srv.Record,
|
||||
}).Info("SRV configuration detected")
|
||||
conf, _ := dns.ClientConfigFromFile("/etc/resolv.conf")
|
||||
dnsServer := net.JoinHostPort(conf.Servers[0], strconv.Itoa(dnsPort))
|
||||
if (config.DnsServer{}) != dev.Srv.Dns {
|
||||
dnsServer = net.JoinHostPort(dev.Srv.Dns.Address, strconv.Itoa(dev.Srv.Dns.Port))
|
||||
log.WithFields(log.Fields{
|
||||
"DnsServer": dnsServer,
|
||||
}).Info("Custom DNS config detected")
|
||||
}
|
||||
dnsMsg := new(dns.Msg)
|
||||
dnsCli := new(dns.Client)
|
||||
|
||||
dnsMsg.RecursionDesired = true
|
||||
dnsMsg.SetQuestion(dns.Fqdn(dev.Srv.Record), dns.TypeSRV)
|
||||
r, _, err := dnsCli.Exchange(dnsMsg, dnsServer)
|
||||
|
||||
if err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
for _, k := range r.Answer {
|
||||
if s, ok := k.(*dns.SRV); ok {
|
||||
d := config.Device{}
|
||||
d.Name = strings.TrimRight(s.Target, ".")
|
||||
d.Address = strings.TrimRight(s.Target, ".")
|
||||
d.User = dev.User
|
||||
d.Password = dev.Password
|
||||
c.getIdentity(&d)
|
||||
realDevices = append(realDevices, d)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
realDevices = append(realDevices, dev)
|
||||
}
|
||||
}
|
||||
|
||||
wg.Add(len(realDevices))
|
||||
|
||||
for _, dev := range realDevices {
|
||||
go func(d config.Device) {
|
||||
c.collectForDevice(d, ch)
|
||||
wg.Done()
|
||||
@ -206,6 +254,30 @@ func (c *collector) Collect(ch chan<- prometheus.Metric) {
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func (c *collector) getIdentity(d *config.Device) error {
|
||||
cl, err := c.connect(d)
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"device": d.Name,
|
||||
"error": err,
|
||||
}).Error("error dialing device")
|
||||
return err
|
||||
}
|
||||
defer cl.Close()
|
||||
reply, err := cl.Run("/system/identity/print")
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{
|
||||
"device": d.Name,
|
||||
"error": err,
|
||||
}).Error("error fetching ethernet interfaces")
|
||||
return err
|
||||
}
|
||||
for _, id := range reply.Re {
|
||||
d.Name = id.Map["name"]
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *collector) collectForDevice(d config.Device, ch chan<- prometheus.Metric) {
|
||||
begin := time.Now()
|
||||
|
||||
|
@ -29,13 +29,23 @@ type Config struct {
|
||||
|
||||
// Device represents a target device
|
||||
type Device struct {
|
||||
Name string `yaml:"name"`
|
||||
Address string `yaml:"address"`
|
||||
User string `yaml:"user"`
|
||||
Password string `yaml:"password"`
|
||||
Name string `yaml:"name"`
|
||||
Address string `yaml:"address,omitempty"`
|
||||
Srv SrvRecord `yaml:"srv,omitempty"`
|
||||
User string `yaml:"user"`
|
||||
Password string `yaml:"password"`
|
||||
Port string `yaml:"port"`
|
||||
}
|
||||
|
||||
type SrvRecord struct {
|
||||
Record string `yaml:"record"`
|
||||
Dns DnsServer `yaml:"dns,omitempty"`
|
||||
}
|
||||
type DnsServer struct {
|
||||
Address string `yaml:"address"`
|
||||
Port int `yaml:"port"`
|
||||
}
|
||||
|
||||
// Load reads YAML from reader and unmashals in Config
|
||||
func Load(r io.Reader) (*Config, error) {
|
||||
b, err := ioutil.ReadAll(r)
|
||||
|
1
go.mod
1
go.mod
@ -3,6 +3,7 @@ module mikrotik-exporter
|
||||
go 1.13
|
||||
|
||||
require (
|
||||
github.com/miekg/dns v1.1.22
|
||||
github.com/prometheus/client_golang v1.2.1
|
||||
github.com/prometheus/common v0.7.0
|
||||
github.com/sirupsen/logrus v1.4.2
|
||||
|
15
go.sum
15
go.sum
@ -32,6 +32,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/miekg/dns v1.1.22 h1:Jm64b3bO9kP43ddLjL2EY3Io6bmy1qGb9Xxz6TqS6rc=
|
||||
github.com/miekg/dns v1.1.22/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||
@ -66,17 +68,30 @@ github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392 h1:ACG4HJsFiNMf47Y4PeRoebLNy/2lXT9EtprMuTFWt1M=
|
||||
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478 h1:l5EDrHhldLYb3ZRHDUhXF7Om7MvYXnkV9/iQNo1lX6g=
|
||||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY=
|
||||
golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
Loading…
Reference in New Issue
Block a user