ip-ddns/app/service.go

123 lines
2.7 KiB
Go
Raw Normal View History

2023-11-17 07:20:10 +01:00
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
}
}
}