123 lines
2.7 KiB
Go
123 lines
2.7 KiB
Go
package app
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"time"
|
|
|
|
"git.ext.icikowski.pl/icikowski/ip-ddns/adapter/directadmin"
|
|
"git.ext.icikowski.pl/icikowski/ip-ddns/adapter/dnsresolver"
|
|
"git.ext.icikowski.pl/icikowski/ip-ddns/config"
|
|
"github.com/rs/zerolog"
|
|
)
|
|
|
|
type Service struct {
|
|
da directadmin.DirectAdminClient
|
|
resolv dnsresolver.DomainNameResolver
|
|
|
|
srcDomain string
|
|
srcNameserver string
|
|
|
|
dstDomain string
|
|
dstNameserver string
|
|
|
|
entryDomain string
|
|
entryName string
|
|
entryTTL uint16
|
|
|
|
resyncTime time.Duration
|
|
|
|
log zerolog.Logger
|
|
}
|
|
|
|
func NewService(
|
|
directadminClient directadmin.DirectAdminClient,
|
|
dnsResolver dnsresolver.DomainNameResolver,
|
|
domainConfig config.DomainConfig,
|
|
resyncTime time.Duration,
|
|
log zerolog.Logger,
|
|
) *Service {
|
|
return &Service{
|
|
da: directadminClient,
|
|
resolv: dnsResolver,
|
|
srcDomain: domainConfig.Source.Name,
|
|
srcNameserver: domainConfig.Source.Nameserver,
|
|
dstDomain: domainConfig.Destination.Name,
|
|
dstNameserver: domainConfig.Destination.Nameserver,
|
|
entryName: domainConfig.Entry.Name,
|
|
entryDomain: domainConfig.Entry.Domain,
|
|
entryTTL: domainConfig.Entry.TTL,
|
|
resyncTime: resyncTime,
|
|
log: log,
|
|
}
|
|
}
|
|
|
|
func (s *Service) update() {
|
|
srcIPs, err := s.resolv.ResolveA(s.srcDomain, s.srcNameserver)
|
|
if err != nil {
|
|
s.log.Warn().Err(err).Msg("unable to get source IP address")
|
|
return
|
|
}
|
|
srcIP := srcIPs[0]
|
|
s.log.Info().IPAddr("ip", srcIP).Msg("got source IP address")
|
|
|
|
dstIPs, err := s.resolv.ResolveA(s.dstDomain, s.dstNameserver)
|
|
if err != nil {
|
|
s.log.Warn().Err(err).Msg("unable to get destination IP address")
|
|
return
|
|
}
|
|
dstIP := dstIPs[0]
|
|
s.log.Info().IPAddr("ip", dstIP).Msg("got destination IP address")
|
|
|
|
if srcIP.Equal(dstIP) {
|
|
s.log.Info().Msg("addresses match, no update needed")
|
|
return
|
|
}
|
|
s.log.Info().Msg("addresses mismatch, updating")
|
|
|
|
params := &directadmin.DNSControlParams{
|
|
Domain: s.entryDomain,
|
|
Action: directadmin.DNSControlActionEdit,
|
|
Type: directadmin.DNSControlRecordTypeA,
|
|
Name: s.entryName,
|
|
Value: srcIP.String(),
|
|
TTL: &s.entryTTL,
|
|
ARECS0: fmt.Sprintf(
|
|
"name=%s&value=%s",
|
|
s.entryName,
|
|
dstIP.String(),
|
|
),
|
|
}
|
|
|
|
log := s.log.With().Object("params", params).Logger()
|
|
|
|
resp, err := s.da.DNSControl(params)
|
|
if err != nil {
|
|
log.Error().Err(err).Msg("unable to update domain params")
|
|
return
|
|
}
|
|
|
|
log = log.With().Object("response", resp).Logger()
|
|
if resp.Error {
|
|
log.Error().Msg("unable to update domain params")
|
|
return
|
|
}
|
|
log.Info().Msg("successfully updated domain params")
|
|
}
|
|
|
|
func (s *Service) Run(ctx context.Context) error {
|
|
ticker := time.NewTicker(s.resyncTime)
|
|
defer ticker.Stop()
|
|
|
|
for {
|
|
s.update()
|
|
|
|
select {
|
|
case <-ctx.Done():
|
|
return nil
|
|
case <-ticker.C:
|
|
continue
|
|
}
|
|
}
|
|
}
|