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:
@@ -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()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user