Skip to content

Commit ffd4f57

Browse files
committed
Better abstraction around daemon
1 parent 74b7b18 commit ffd4f57

File tree

2 files changed

+71
-36
lines changed

2 files changed

+71
-36
lines changed

ddns/ddns.go

Lines changed: 63 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,30 @@ type DDNSProvider interface {
1616
Update(domain, record, ip string) error
1717
}
1818

19+
type IPProvider interface {
20+
Get() (ip string, err error)
21+
}
22+
23+
type ConfigProvider interface {
24+
Get() (domain, record string, err error)
25+
}
26+
27+
type ipProvider struct{}
28+
29+
func (p *ipProvider) Get() (string, error) {
30+
ip, err := ip.GetPublicIPWithRetry(10, 5*time.Second)
31+
if err != nil {
32+
return "", errors.Trace(err)
33+
}
34+
return ip, nil
35+
}
36+
37+
type configProvider struct{}
38+
39+
func (p *configProvider) Get() (domain, record string, err error) {
40+
return conf.Domain.Get(), conf.Record.Get(), nil
41+
}
42+
1943
type Daemon interface {
2044
Update(provider DDNSProvider) error
2145
Start(provider DDNSProvider, updatePeriod, failureRetryDelay time.Duration) error
@@ -24,37 +48,67 @@ type Daemon interface {
2448

2549
type DDNSDaemon struct {
2650
Daemon
27-
shouldRun bool
51+
shouldRun bool
52+
ddnsProvider DDNSProvider
53+
ipProvider IPProvider
54+
configProvider ConfigProvider
55+
}
56+
57+
// NewDDNSDaemon creates a new DDNSDaemon
58+
func NewDDNSDaemon(ddnsProvider DDNSProvider, ipProvider IPProvider, configProvider ConfigProvider) *DDNSDaemon {
59+
if ddnsProvider == nil {
60+
panic("ddnsProvider must not be nil")
61+
}
62+
if ipProvider == nil {
63+
panic("ipProvider must not be nil")
64+
}
65+
if configProvider == nil {
66+
panic("configProvider must not be nil")
67+
}
68+
return &DDNSDaemon{
69+
shouldRun: true,
70+
ddnsProvider: ddnsProvider,
71+
ipProvider: ipProvider,
72+
configProvider: configProvider,
73+
}
2874
}
2975

3076
// Update performs a one time DDNS update.
31-
func (d *DDNSDaemon) Update(provider DDNSProvider) error {
32-
ip, err := ip.GetPublicIPWithRetry(10, 5*time.Second)
77+
func (d *DDNSDaemon) Update() error {
78+
ip, err := d.ipProvider.Get()
3379
if err != nil {
3480
return errors.Annotate(err, "unable to retrieve public IP")
3581
}
3682
log.Info().Msgf("Found public IP '%s'", ip)
37-
err = provider.Update(conf.Domain.Get(), conf.Record.Get(), ip)
83+
domain, record, err := d.configProvider.Get()
84+
if err != nil {
85+
return errors.Annotate(err, "unable to find domain or record in configuration")
86+
}
87+
err = d.ddnsProvider.Update(domain, record, ip)
3888
return errors.Annotatef(err, "failed to update DNS")
3989
}
4090

4191
// Start continually keeps DDNS up to date.
4292
// updatePeriod - how often to check for updates
4393
// failureRetryDelay - how long to wait until retry after a failure
44-
func (d *DDNSDaemon) Start(provider DDNSProvider, updatePeriod, failureRetryDelay time.Duration) error {
94+
func (d *DDNSDaemon) Start(updatePeriod, failureRetryDelay time.Duration) error {
4595
var lastIP string
4696
var lastIPUpdate time.Time
4797

4898
log.Info().Msgf("Daemon running, will now monitor for IP updates every %d seconds", int(updatePeriod.Seconds()))
4999

50100
for d.shouldRun {
51-
dnsRecordIP, err := provider.Get(conf.Domain.Get(), conf.Record.Get())
101+
domain, record, err := d.configProvider.Get()
102+
if err != nil {
103+
return errors.Annotate(err, "unable to find domain or record in configuration")
104+
}
105+
dnsRecordIP, err := d.ddnsProvider.Get(domain, record)
52106
if err != nil {
53107
log.Error().Msgf("Unable to look up current DNS record, will retry in %d seconds. Error was:\n%v", int(updatePeriod.Seconds()), err)
54108
time.Sleep(failureRetryDelay)
55109
continue
56110
}
57-
newIP, err := ip.GetPublicIPWithRetry(10, 5*time.Second)
111+
newIP, err := d.ipProvider.Get()
58112
if err != nil {
59113
log.Error().Msgf("Unable to retrieve public IP, will retry in %d seconds. Error was:\n%v", int(updatePeriod.Seconds()), err)
60114
time.Sleep(failureRetryDelay)
@@ -81,7 +135,7 @@ func (d *DDNSDaemon) Start(provider DDNSProvider, updatePeriod, failureRetryDela
81135
lastIP = newIP
82136
lastIPUpdate = time.Now()
83137

84-
err = provider.Update(conf.Domain.Get(), conf.Record.Get(), lastIP)
138+
err = d.ddnsProvider.Update(domain, record, lastIP)
85139
if err != nil {
86140
log.Error().Msgf("Unable to update DNS, will retry in %d seconds. Erorr was:\n%v", updatePeriod/time.Second, err)
87141
time.Sleep(failureRetryDelay)
@@ -98,7 +152,7 @@ func (d *DDNSDaemon) Start(provider DDNSProvider, updatePeriod, failureRetryDela
98152
// StartWithDefaults calls Start but with default values
99153
func (d *DDNSDaemon) StartWithDefaults(provider DDNSProvider) error {
100154
t := 10 * time.Second
101-
return errors.Trace(d.Start(provider, t, t))
155+
return errors.Trace(d.Start(t, t))
102156
}
103157

104158
func (d *DDNSDaemon) Stop() {

ddns/ddns_test.go

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,24 @@ package ddns
22

33
import (
44
"testing"
5-
"time"
65

76
"github.com/golang/mock/gomock"
87
"github.com/stretchr/testify/assert"
98
)
109

11-
// mockDaemon is a mock DDNSDaemon
12-
type mockDaemon struct {
13-
DDNSDaemon
14-
domain, record, ip string
15-
}
16-
17-
func (p *mockDaemon) Update(provider DDNSProvider) error {
18-
return provider.Update(p.domain, p.record, p.ip)
19-
}
20-
21-
func (p *mockDaemon) Start(provider DDNSProvider, updatePeriod, failureRetryDelay time.Duration) error {
22-
return nil
23-
}
24-
25-
func (p *mockDaemon) Stop() error {
26-
return nil
27-
}
28-
2910
func TestDDNSDaemon(t *testing.T) {
3011
assert := assert.New(t)
3112
ctrl := gomock.NewController(t)
3213
defer ctrl.Finish()
33-
d := mockDaemon{}
14+
d := NewMockDaemon(ctrl)
3415
p := NewMockDDNSProvider(ctrl)
35-
d.domain = "abc.com"
36-
d.record = "xyz.abc.com"
37-
d.ip = "1.1.1.1"
38-
p.EXPECT().Update(d.domain, d.record, d.ip).Return(nil).Times(1)
39-
p.EXPECT().Get(d.domain, d.record).Return(d.ip, nil).Times(1)
16+
domain := "abc.com"
17+
record := "xyz.abc.com"
18+
ip := "1.1.1.1"
19+
p.EXPECT().Update(gomock.Eq(domain), gomock.Eq(record), gomock.Eq(ip)).Return(nil).Times(1)
20+
p.EXPECT().Get(domain, record).Return(ip, nil).Times(1)
4021
assert.NoError(d.Update(p))
41-
ip, err := p.Get(d.domain, d.record)
22+
ip, err := p.Get(domain)
4223
assert.NoError(err)
43-
assert.Equal(d.ip, ip)
24+
assert.Equal(ip, ip)
4425
}

0 commit comments

Comments
 (0)