Skip to content

Commit dc489b7

Browse files
authored
Consider SRV records with port 0 as an error (#900)
* sd/dnssrv: fix Instancer method receivers * sd/dnssrv: SRV record with port 0 is an error * sd/dnssrv: test for SRV port zero issue * .build.yml: update and fix
1 parent b3415e3 commit dc489b7

2 files changed

Lines changed: 50 additions & 14 deletions

File tree

sd/dnssrv/instancer.go

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package dnssrv
22

33
import (
4+
"errors"
45
"fmt"
56
"net"
67
"time"
@@ -10,6 +11,11 @@ import (
1011
"github.com/go-kit/kit/sd/internal/instance"
1112
)
1213

14+
// ErrPortZero is returned by the resolve machinery
15+
// when a DNS resolver returns an SRV record with its
16+
// port set to zero.
17+
var ErrPortZero = errors.New("resolver returned SRV record with port 0")
18+
1319
// Instancer yields instances from the named DNS SRV record. The name is
1420
// resolved on a fixed schedule. Priorities and weights are ignored.
1521
type Instancer struct {
@@ -57,47 +63,50 @@ func NewInstancerDetailed(
5763
}
5864

5965
// Stop terminates the Instancer.
60-
func (p *Instancer) Stop() {
61-
close(p.quit)
66+
func (in *Instancer) Stop() {
67+
close(in.quit)
6268
}
6369

64-
func (p *Instancer) loop(t *time.Ticker, lookup Lookup) {
70+
func (in *Instancer) loop(t *time.Ticker, lookup Lookup) {
6571
defer t.Stop()
6672
for {
6773
select {
6874
case <-t.C:
69-
instances, err := p.resolve(lookup)
75+
instances, err := in.resolve(lookup)
7076
if err != nil {
71-
p.logger.Log("name", p.name, "err", err)
72-
p.cache.Update(sd.Event{Err: err})
77+
in.logger.Log("name", in.name, "err", err)
78+
in.cache.Update(sd.Event{Err: err})
7379
continue // don't replace potentially-good with bad
7480
}
75-
p.cache.Update(sd.Event{Instances: instances})
81+
in.cache.Update(sd.Event{Instances: instances})
7682

77-
case <-p.quit:
83+
case <-in.quit:
7884
return
7985
}
8086
}
8187
}
8288

83-
func (p *Instancer) resolve(lookup Lookup) ([]string, error) {
84-
_, addrs, err := lookup("", "", p.name)
89+
func (in *Instancer) resolve(lookup Lookup) ([]string, error) {
90+
_, addrs, err := lookup("", "", in.name)
8591
if err != nil {
8692
return nil, err
8793
}
8894
instances := make([]string, len(addrs))
8995
for i, addr := range addrs {
96+
if addr.Port == 0 {
97+
return nil, ErrPortZero
98+
}
9099
instances[i] = net.JoinHostPort(addr.Target, fmt.Sprint(addr.Port))
91100
}
92101
return instances, nil
93102
}
94103

95104
// Register implements Instancer.
96-
func (s *Instancer) Register(ch chan<- sd.Event) {
97-
s.cache.Register(ch)
105+
func (in *Instancer) Register(ch chan<- sd.Event) {
106+
in.cache.Register(ch)
98107
}
99108

100109
// Deregister implements Instancer.
101-
func (s *Instancer) Deregister(ch chan<- sd.Event) {
102-
s.cache.Deregister(ch)
110+
func (in *Instancer) Deregister(ch chan<- sd.Event) {
111+
in.cache.Deregister(ch)
103112
}

sd/dnssrv/instancer_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,33 @@ func TestRefresh(t *testing.T) {
6868
}
6969
}
7070

71+
func TestIssue892(t *testing.T) {
72+
ticker := time.NewTicker(time.Second)
73+
ticker.Stop()
74+
tickc := make(chan time.Time)
75+
ticker.C = tickc
76+
77+
records := []*net.SRV{
78+
{Target: "1.0.0.1", Port: 80},
79+
{Target: "1.0.0.2", Port: 0},
80+
{Target: "1.0.0.3", Port: 80},
81+
}
82+
83+
lookup := func(service, proto, name string) (string, []*net.SRV, error) {
84+
return "cname", records, nil
85+
}
86+
87+
instancer := NewInstancerDetailed("name", ticker, lookup, log.NewNopLogger())
88+
defer instancer.Stop()
89+
90+
tickc <- time.Now()
91+
time.Sleep(100 * time.Millisecond)
92+
93+
if want, have := ErrPortZero, instancer.cache.State().Err; want != have {
94+
t.Fatalf("want %v, have %v", want, have)
95+
}
96+
}
97+
7198
type nopCloser struct{}
7299

73100
func (nopCloser) Close() error { return nil }

0 commit comments

Comments
 (0)