156 lines
4.0 KiB
Go
156 lines
4.0 KiB
Go
package watcher
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/datahearth/ddnsclient/pkg/providers"
|
|
"github.com/datahearth/ddnsclient/pkg/subdomain"
|
|
"github.com/datahearth/ddnsclient/pkg/utils"
|
|
"github.com/sirupsen/logrus"
|
|
)
|
|
|
|
type Watcher interface {
|
|
Run(*time.Ticker, chan struct{}, chan error)
|
|
}
|
|
|
|
type watcher struct {
|
|
logger logrus.FieldLogger
|
|
provider providers.Provider
|
|
subdomains []subdomain.Subdomain
|
|
pendingSubdomains subdomain.PendingSubdomains
|
|
firstRun bool
|
|
pendingDnsPropagation int
|
|
webIP string
|
|
providerName string
|
|
}
|
|
|
|
// NewWatcher creates a watcher a given provider and its subdomains
|
|
func NewWatcher(logger logrus.FieldLogger, provider providers.Provider, sbs []string, webIP, providerName string, pendingDnsPropagation int) (Watcher, error) {
|
|
if logger == nil {
|
|
return nil, utils.ErrNilLogger
|
|
}
|
|
if provider == nil {
|
|
return nil, utils.ErrNilProvider
|
|
}
|
|
if webIP == "" {
|
|
webIP = "http://dynamicdns.park-your-domain.com/getip"
|
|
}
|
|
if pendingDnsPropagation == 0 {
|
|
pendingDnsPropagation = 180
|
|
}
|
|
logger = logger.WithField("pkg", "watcher")
|
|
|
|
subdomains := make([]subdomain.Subdomain, len(sbs))
|
|
for i, sb := range sbs {
|
|
sub, err := subdomain.NewSubdomain(logger, sb)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
subdomains[i] = sub
|
|
}
|
|
|
|
return &watcher{
|
|
logger: logger,
|
|
provider: provider,
|
|
subdomains: subdomains,
|
|
webIP: webIP,
|
|
firstRun: true,
|
|
pendingSubdomains: make(map[time.Time]subdomain.Subdomain),
|
|
pendingDnsPropagation: pendingDnsPropagation,
|
|
providerName: providerName,
|
|
}, nil
|
|
}
|
|
|
|
func (w *watcher) Run(t *time.Ticker, chClose chan struct{}, chErr chan error) {
|
|
logger := w.logger.WithField("component", "Run")
|
|
|
|
go w.checkPendingSubdomains(chClose)
|
|
if w.firstRun {
|
|
if err := w.runDDNSCheck(); err != nil {
|
|
chErr <- err
|
|
}
|
|
w.firstRun = false
|
|
}
|
|
|
|
for {
|
|
select {
|
|
case <-chClose:
|
|
t.Stop()
|
|
logger.Infoln("Close watcher channel triggered. Ticker stopped")
|
|
return
|
|
case <-t.C:
|
|
if err := w.runDDNSCheck(); err != nil {
|
|
chErr <- err
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func (w *watcher) runDDNSCheck() error {
|
|
logger := w.logger.WithField("component", "runDDNSCheck")
|
|
|
|
logger.Infof("Starting [%s] DDNS check...\n", w.providerName)
|
|
|
|
srvIP, err := utils.RetrieveServerIP(w.webIP)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
logger.Debugln("Checking server IP...")
|
|
|
|
for _, sb := range w.subdomains {
|
|
if sb.SubIsPending(w.pendingSubdomains) {
|
|
continue
|
|
}
|
|
|
|
logger.Debugf("Checking subdomain %s...\n", sb.GetSubdomainAddr())
|
|
ok, err := sb.CheckIPAddr(srvIP)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
subAddr := sb.GetSubdomainAddr()
|
|
if !ok {
|
|
logger.WithFields(logrus.Fields{
|
|
"server-ip": srvIP,
|
|
"subdomain-address": subAddr,
|
|
}).Infoln("IP addresses doesn't match. Updating subdomain's ip...")
|
|
if err := w.provider.UpdateIP(subAddr, srvIP); err != nil {
|
|
return err
|
|
}
|
|
logger.WithFields(logrus.Fields{
|
|
"server-ip": srvIP,
|
|
"subdomain-address": subAddr,
|
|
}).Infoln("Subdomain's ip updated! Removing from checks for 5 mins")
|
|
|
|
w.pendingSubdomains[time.Now()] = sb
|
|
|
|
continue
|
|
}
|
|
|
|
logger.Debugf("%s is up to date. \n", subAddr)
|
|
}
|
|
|
|
logger.Infof("[%s] DDNS check finished\n", w.providerName)
|
|
return nil
|
|
}
|
|
|
|
func (w *watcher) checkPendingSubdomains(chClose chan struct{}) {
|
|
logger := w.logger.WithField("component", "checkPendingSubdomains")
|
|
t := time.NewTicker(time.Second * time.Duration(w.pendingDnsPropagation))
|
|
|
|
logger.Debugln("Start checking for pending subdomains...")
|
|
for {
|
|
select {
|
|
case <-chClose:
|
|
logger.Debugln("Close pending subdomains")
|
|
return
|
|
case <-t.C:
|
|
logger.Debugln("Checking pending subdomains...")
|
|
if delSbs := subdomain.CheckPendingSubdomains(w.pendingSubdomains, time.Now()); delSbs != nil {
|
|
w.pendingSubdomains = subdomain.DeletePendingSubdomains(delSbs, w.pendingSubdomains)
|
|
logger.Debugln("Pendings subdomains found. Cleaned.")
|
|
}
|
|
}
|
|
}
|
|
}
|