diff options
-rw-r--r-- | go.mod | 1 | ||||
-rw-r--r-- | go.sum | 2 | ||||
-rw-r--r-- | plugin/hosts/README.md | 11 | ||||
-rw-r--r-- | plugin/hosts/hosts.go | 30 | ||||
-rw-r--r-- | plugin/hosts/hosts_test.go | 10 | ||||
-rw-r--r-- | plugin/hosts/hostsfile.go | 157 | ||||
-rw-r--r-- | plugin/hosts/hostsfile_test.go | 74 | ||||
-rw-r--r-- | plugin/hosts/setup.go | 6 | ||||
-rw-r--r-- | plugin/hosts/setup_test.go | 27 |
9 files changed, 147 insertions, 171 deletions
@@ -54,6 +54,7 @@ require ( golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 // indirect golang.org/x/net v0.0.0-20190628185345-da137c7871d7 // indirect golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb + golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 // indirect google.golang.org/genproto v0.0.0-20190701230453-710ae3a149df // indirect google.golang.org/grpc v1.22.0 gopkg.in/DataDog/dd-trace-go.v1 v1.16.0 @@ -325,6 +325,8 @@ golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624190245-7f2218787638/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7 h1:9zdDQZ7Thm29KFXgAX/+yaf3eVbP7djjWp/dXAppNCc= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= diff --git a/plugin/hosts/README.md b/plugin/hosts/README.md index d42714828..60135e71a 100644 --- a/plugin/hosts/README.md +++ b/plugin/hosts/README.md @@ -11,14 +11,16 @@ file that exists on disk. It checks the file for changes and updates the zones a plugin only supports A, AAAA, and PTR records. The hosts plugin can be used with readily available hosts files that block access to advertising servers. -The plugin reloads the content of the hosts file every 5 seconds. Upon reload, CoreDNS will use the new definitions. -Should the file be deleted, any inlined content will continue to be served. When the file is restored, it will then again be used. +The plugin reloads the content of the hosts file every 5 seconds. Upon reload, CoreDNS will use the +new definitions. Should the file be deleted, any inlined content will continue to be served. When +the file is restored, it will then again be used. This plugin can only be used once per Server Block. ## The hosts file -Commonly the entries are of the form `IP_address canonical_hostname [aliases...]` as explained by the hosts(5) man page. +Commonly the entries are of the form `IP_address canonical_hostname [aliases...]` as explained by +the hosts(5) man page. Examples: @@ -34,7 +36,8 @@ fdfc:a744:27b5:3b0e::1 example.com example ### PTR records -PTR records for reverse lookups are generated automatically by CoreDNS (based on the hosts file entries) and cannot be created manually. +PTR records for reverse lookups are generated automatically by CoreDNS (based on the hosts file +entries) and cannot be created manually. ## Syntax diff --git a/plugin/hosts/hosts.go b/plugin/hosts/hosts.go index 8650053c0..54b090b4d 100644 --- a/plugin/hosts/hosts.go +++ b/plugin/hosts/hosts.go @@ -31,7 +31,7 @@ func (h Hosts) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) ( if zone == "" { // PTR zones don't need to be specified in Origins if state.Type() != "PTR" { - // If this doesn't match we need to fall through regardless of h.Fallthrough + // if this doesn't match we need to fall through regardless of h.Fallthrough return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r) } } @@ -89,7 +89,6 @@ func (h Hosts) otherRecordsExist(qtype uint16, qname string) bool { } } return false - } // Name implements the plugin.Handle interface. @@ -97,39 +96,36 @@ func (h Hosts) Name() string { return "hosts" } // a takes a slice of net.IPs and returns a slice of A RRs. func a(zone string, ttl uint32, ips []net.IP) []dns.RR { - answers := []dns.RR{} - for _, ip := range ips { + answers := make([]dns.RR, len(ips)) + for i, ip := range ips { r := new(dns.A) - r.Hdr = dns.RR_Header{Name: zone, Rrtype: dns.TypeA, - Class: dns.ClassINET, Ttl: ttl} + r.Hdr = dns.RR_Header{Name: zone, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: ttl} r.A = ip - answers = append(answers, r) + answers[i] = r } return answers } // aaaa takes a slice of net.IPs and returns a slice of AAAA RRs. func aaaa(zone string, ttl uint32, ips []net.IP) []dns.RR { - answers := []dns.RR{} - for _, ip := range ips { + answers := make([]dns.RR, len(ips)) + for i, ip := range ips { r := new(dns.AAAA) - r.Hdr = dns.RR_Header{Name: zone, Rrtype: dns.TypeAAAA, - Class: dns.ClassINET, Ttl: ttl} + r.Hdr = dns.RR_Header{Name: zone, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: ttl} r.AAAA = ip - answers = append(answers, r) + answers[i] = r } return answers } // ptr takes a slice of host names and filters out the ones that aren't in Origins, if specified, and returns a slice of PTR RRs. func (h *Hosts) ptr(zone string, ttl uint32, names []string) []dns.RR { - answers := []dns.RR{} - for _, n := range names { + answers := make([]dns.RR, len(names)) + for i, n := range names { r := new(dns.PTR) - r.Hdr = dns.RR_Header{Name: zone, Rrtype: dns.TypePTR, - Class: dns.ClassINET, Ttl: ttl} + r.Hdr = dns.RR_Header{Name: zone, Rrtype: dns.TypePTR, Class: dns.ClassINET, Ttl: ttl} r.Ptr = dns.Fqdn(n) - answers = append(answers, r) + answers[i] = r } return answers } diff --git a/plugin/hosts/hosts_test.go b/plugin/hosts/hosts_test.go index 975710bb3..062c99851 100644 --- a/plugin/hosts/hosts_test.go +++ b/plugin/hosts/hosts_test.go @@ -2,7 +2,6 @@ package hosts import ( "context" - "io" "strings" "testing" @@ -12,20 +11,17 @@ import ( "github.com/miekg/dns" ) -func (h *Hostsfile) parseReader(r io.Reader) { - h.hmap = h.parse(r) -} - func TestLookupA(t *testing.T) { h := Hosts{ Next: test.ErrorHandler(), Hostsfile: &Hostsfile{ Origins: []string{"."}, - hmap: newHostsMap(), + hmap: newMap(), + inline: newMap(), options: newOptions(), }, } - h.parseReader(strings.NewReader(hostsExample)) + h.hmap = h.parse(strings.NewReader(hostsExample)) ctx := context.TODO() diff --git a/plugin/hosts/hostsfile.go b/plugin/hosts/hostsfile.go index 421f8a77c..f7cc73528 100644 --- a/plugin/hosts/hostsfile.go +++ b/plugin/hosts/hostsfile.go @@ -19,7 +19,8 @@ import ( "github.com/coredns/coredns/plugin" ) -func parseLiteralIP(addr string) net.IP { +// parseIP calls discards any v6 zone info, before calling net.ParseIP. +func parseIP(addr string) net.IP { if i := strings.Index(addr, "%"); i >= 0 { // discard ipv6 zone addr = addr[0:i] @@ -28,10 +29,6 @@ func parseLiteralIP(addr string) net.IP { return net.ParseIP(addr) } -func absDomainName(b string) string { - return plugin.Name(b).Normalize() -} - type options struct { // automatically generate IP to Hostname PTR entries // for host entries we parse @@ -48,48 +45,40 @@ func newOptions() *options { return &options{ autoReverse: true, ttl: 3600, - reload: durationOf5s, + reload: time.Duration(5 * time.Second), } } -type hostsMap struct { - // Key for the list of literal IP addresses must be a host - // name. It would be part of DNS labels, a FQDN or an absolute - // FQDN. - // For now the key is converted to lower case for convenience. - byNameV4 map[string][]net.IP - byNameV6 map[string][]net.IP +// Map contains the IPv4/IPv6 and reverse mapping. +type Map struct { + // Key for the list of literal IP addresses must be a FQDN lowercased host name. + name4 map[string][]net.IP + name6 map[string][]net.IP // Key for the list of host names must be a literal IP address - // including IPv6 address with zone identifier. + // including IPv6 address without zone identifier. // We don't support old-classful IP address notation. - byAddr map[string][]string + addr map[string][]string } -const ( - durationOf0s = time.Duration(0) - durationOf5s = time.Duration(5 * time.Second) -) - -func newHostsMap() *hostsMap { - return &hostsMap{ - byNameV4: make(map[string][]net.IP), - byNameV6: make(map[string][]net.IP), - byAddr: make(map[string][]string), +func newMap() *Map { + return &Map{ + name4: make(map[string][]net.IP), + name6: make(map[string][]net.IP), + addr: make(map[string][]string), } } -// Len returns the total number of addresses in the hostmap, this includes -// V4/V6 and any reverse addresses. -func (h *hostsMap) Len() int { +// Len returns the total number of addresses in the hostmap, this includes V4/V6 and any reverse addresses. +func (h *Map) Len() int { l := 0 - for _, v4 := range h.byNameV4 { + for _, v4 := range h.name4 { l += len(v4) } - for _, v6 := range h.byNameV6 { + for _, v6 := range h.name6 { l += len(v6) } - for _, a := range h.byAddr { + for _, a := range h.addr { l += len(a) } return l @@ -103,11 +92,10 @@ type Hostsfile struct { Origins []string // hosts maps for lookups - hmap *hostsMap + hmap *Map // inline saves the hosts file that is inlined in a Corefile. - // We need a copy here as we want to use it to initialize the maps for parse. - inline *hostsMap + inline *Map // path to the hosts file path string @@ -132,6 +120,7 @@ func (h *Hostsfile) readHosts() { h.RLock() size := h.size h.RUnlock() + if err == nil && h.mtime.Equal(stat.ModTime()) && size == stat.Size() { return } @@ -155,12 +144,11 @@ func (h *Hostsfile) initInline(inline []string) { } h.inline = h.parse(strings.NewReader(strings.Join(inline, "\n"))) - *h.hmap = *h.inline } -// Parse reads the hostsfile and populates the byName and byAddr maps. -func (h *Hostsfile) parse(r io.Reader) *hostsMap { - hmap := newHostsMap() +// Parse reads the hostsfile and populates the byName and addr maps. +func (h *Hostsfile) parse(r io.Reader) *Map { + hmap := newMap() scanner := bufio.NewScanner(r) for scanner.Scan() { @@ -173,73 +161,52 @@ func (h *Hostsfile) parse(r io.Reader) *hostsMap { if len(f) < 2 { continue } - addr := parseLiteralIP(string(f[0])) + addr := parseIP(string(f[0])) if addr == nil { continue } - ver := ipVersion(string(f[0])) + + family := 0 + if addr.To4() != nil { + family = 1 + } else { + family = 2 + } + for i := 1; i < len(f); i++ { - name := absDomainName(string(f[i])) + name := plugin.Name(string(f[i])).Normalize() if plugin.Zones(h.Origins).Matches(name) == "" { // name is not in Origins continue } - switch ver { - case 4: - hmap.byNameV4[name] = append(hmap.byNameV4[name], addr) - case 6: - hmap.byNameV6[name] = append(hmap.byNameV6[name], addr) + switch family { + case 1: + hmap.name4[name] = append(hmap.name4[name], addr) + case 2: + hmap.name6[name] = append(hmap.name6[name], addr) default: continue } if !h.options.autoReverse { continue } - hmap.byAddr[addr.String()] = append(hmap.byAddr[addr.String()], name) + hmap.addr[addr.String()] = append(hmap.addr[addr.String()], name) } } - for name := range h.hmap.byNameV4 { - hmap.byNameV4[name] = append(hmap.byNameV4[name], h.hmap.byNameV4[name]...) - } - for name := range h.hmap.byNameV4 { - hmap.byNameV6[name] = append(hmap.byNameV6[name], h.hmap.byNameV6[name]...) - } - - for addr := range h.hmap.byAddr { - hmap.byAddr[addr] = append(hmap.byAddr[addr], h.hmap.byAddr[addr]...) - } - return hmap } -// ipVersion returns what IP version was used textually -// For why the string is parsed end to start, -// see IPv4-Compatible IPv6 addresses - RFC 4291 section 2.5.5 -func ipVersion(s string) int { - for i := len(s) - 1; i >= 0; i-- { - switch s[i] { - case '.': - return 4 - case ':': - return 6 - } - } - return 0 -} - -// LookupStaticHost looks up the IP addresses for the given host from the hosts file. -func (h *Hostsfile) lookupStaticHost(hmapByName map[string][]net.IP, host string) []net.IP { - fqhost := absDomainName(host) - +// lookupStaticHost looks up the IP addresses for the given host from the hosts file. +func (h *Hostsfile) lookupStaticHost(m map[string][]net.IP, host string) []net.IP { h.RLock() defer h.RUnlock() - if len(hmapByName) == 0 { + if len(m) == 0 { return nil } - ips, ok := hmapByName[fqhost] + ips, ok := m[host] if !ok { return nil } @@ -250,30 +217,38 @@ func (h *Hostsfile) lookupStaticHost(hmapByName map[string][]net.IP, host string // LookupStaticHostV4 looks up the IPv4 addresses for the given host from the hosts file. func (h *Hostsfile) LookupStaticHostV4(host string) []net.IP { - return h.lookupStaticHost(h.hmap.byNameV4, host) + host = strings.ToLower(host) + ip1 := h.lookupStaticHost(h.hmap.name4, host) + ip2 := h.lookupStaticHost(h.inline.name4, host) + return append(ip1, ip2...) } // LookupStaticHostV6 looks up the IPv6 addresses for the given host from the hosts file. func (h *Hostsfile) LookupStaticHostV6(host string) []net.IP { - return h.lookupStaticHost(h.hmap.byNameV6, host) + host = strings.ToLower(host) + ip1 := h.lookupStaticHost(h.hmap.name6, host) + ip2 := h.lookupStaticHost(h.inline.name6, host) + return append(ip1, ip2...) } // LookupStaticAddr looks up the hosts for the given address from the hosts file. func (h *Hostsfile) LookupStaticAddr(addr string) []string { - h.RLock() - defer h.RUnlock() - addr = parseLiteralIP(addr).String() + addr = parseIP(addr).String() if addr == "" { return nil } - if len(h.hmap.byAddr) == 0 { - return nil - } - hosts, ok := h.hmap.byAddr[addr] - if !ok { + + h.RLock() + defer h.RUnlock() + hosts1, _ := h.hmap.addr[addr] + hosts2, _ := h.inline.addr[addr] + + if len(hosts1) == 0 && len(hosts2) == 0 { return nil } - hostsCp := make([]string, len(hosts)) - copy(hostsCp, hosts) + + hostsCp := make([]string, len(hosts1)+len(hosts2)) + copy(hostsCp, hosts1) + copy(hostsCp[len(hosts1):], hosts2) return hostsCp } diff --git a/plugin/hosts/hostsfile_test.go b/plugin/hosts/hostsfile_test.go index db0e63d75..626b8918d 100644 --- a/plugin/hosts/hostsfile_test.go +++ b/plugin/hosts/hostsfile_test.go @@ -9,15 +9,18 @@ import ( "reflect" "strings" "testing" + + "github.com/coredns/coredns/plugin" ) func testHostsfile(file string) *Hostsfile { h := &Hostsfile{ Origins: []string{"."}, - hmap: newHostsMap(), + hmap: newMap(), + inline: newMap(), options: newOptions(), } - h.parseReader(strings.NewReader(file)) + h.hmap = h.parse(strings.NewReader(file)) return h } @@ -74,44 +77,43 @@ var lookupStaticHostTests = []struct { { hosts, []staticHostEntry{ - {"odin", []string{"127.0.0.2", "127.0.0.3"}, []string{"::2"}}, - {"thor", []string{"127.1.1.1"}, []string{}}, - {"ullr", []string{"127.1.1.2"}, []string{}}, - {"ullrhost", []string{"127.1.1.2"}, []string{}}, - {"localhost", []string{}, []string{"fe80::1"}}, + {"odin.", []string{"127.0.0.2", "127.0.0.3"}, []string{"::2"}}, + {"thor.", []string{"127.1.1.1"}, []string{}}, + {"ullr.", []string{"127.1.1.2"}, []string{}}, + {"ullrhost.", []string{"127.1.1.2"}, []string{}}, + {"localhost.", []string{}, []string{"fe80::1"}}, }, }, { singlelinehosts, // see golang.org/issue/6646 []staticHostEntry{ - {"odin", []string{"127.0.0.2"}, []string{}}, + {"odin.", []string{"127.0.0.2"}, []string{}}, }, }, { ipv4hosts, []staticHostEntry{ - {"localhost", []string{"127.0.0.1", "127.0.0.2", "127.0.0.3"}, []string{}}, - {"localhost.localdomain", []string{"127.0.0.3"}, []string{}}, + {"localhost.", []string{"127.0.0.1", "127.0.0.2", "127.0.0.3"}, []string{}}, + {"localhost.localdomain.", []string{"127.0.0.3"}, []string{}}, }, }, { ipv6hosts, []staticHostEntry{ - {"localhost", []string{}, []string{"::1", "fe80::1", "fe80::2", "fe80::3"}}, - {"localhost.localdomain", []string{}, []string{"fe80::3"}}, + {"localhost.", []string{}, []string{"::1", "fe80::1", "fe80::2", "fe80::3"}}, + {"localhost.localdomain.", []string{}, []string{"fe80::3"}}, }, }, { casehosts, []staticHostEntry{ - {"PreserveMe", []string{"127.0.0.1"}, []string{"::1"}}, - {"PreserveMe.local", []string{"127.0.0.1"}, []string{"::1"}}, + {"PreserveMe.", []string{"127.0.0.1"}, []string{"::1"}}, + {"PreserveMe.local.", []string{"127.0.0.1"}, []string{"::1"}}, }, }, } func TestLookupStaticHost(t *testing.T) { - for _, tt := range lookupStaticHostTests { h := testHostsfile(tt.file) for _, ent := range tt.ents { @@ -121,7 +123,7 @@ func TestLookupStaticHost(t *testing.T) { } func testStaticHost(t *testing.T, ent staticHostEntry, h *Hostsfile) { - ins := []string{ent.in, absDomainName(ent.in), strings.ToLower(ent.in), strings.ToUpper(ent.in)} + ins := []string{ent.in, plugin.Name(ent.in).Normalize(), strings.ToLower(ent.in), strings.ToUpper(ent.in)} for k, in := range ins { addrsV4 := h.LookupStaticHostV4(in) if len(addrsV4) != len(ent.v4) { @@ -156,43 +158,43 @@ var lookupStaticAddrTests = []struct { { hosts, []staticIPEntry{ - {"255.255.255.255", []string{"broadcasthost"}}, - {"127.0.0.2", []string{"odin"}}, - {"127.0.0.3", []string{"odin"}}, - {"::2", []string{"odin"}}, - {"127.1.1.1", []string{"thor"}}, - {"127.1.1.2", []string{"ullr", "ullrhost"}}, - {"fe80::1", []string{"localhost"}}, + {"255.255.255.255", []string{"broadcasthost."}}, + {"127.0.0.2", []string{"odin."}}, + {"127.0.0.3", []string{"odin."}}, + {"::2", []string{"odin."}}, + {"127.1.1.1", []string{"thor."}}, + {"127.1.1.2", []string{"ullr.", "ullrhost."}}, + {"fe80::1", []string{"localhost."}}, }, }, { singlelinehosts, // see golang.org/issue/6646 []staticIPEntry{ - {"127.0.0.2", []string{"odin"}}, + {"127.0.0.2", []string{"odin."}}, }, }, { ipv4hosts, // see golang.org/issue/8996 []staticIPEntry{ - {"127.0.0.1", []string{"localhost"}}, - {"127.0.0.2", []string{"localhost"}}, - {"127.0.0.3", []string{"localhost", "localhost.localdomain"}}, + {"127.0.0.1", []string{"localhost."}}, + {"127.0.0.2", []string{"localhost."}}, + {"127.0.0.3", []string{"localhost.", "localhost.localdomain."}}, }, }, { ipv6hosts, // see golang.org/issue/8996 []staticIPEntry{ - {"::1", []string{"localhost"}}, - {"fe80::1", []string{"localhost"}}, - {"fe80::2", []string{"localhost"}}, - {"fe80::3", []string{"localhost", "localhost.localdomain"}}, + {"::1", []string{"localhost."}}, + {"fe80::1", []string{"localhost."}}, + {"fe80::2", []string{"localhost."}}, + {"fe80::3", []string{"localhost.", "localhost.localdomain."}}, }, }, { casehosts, // see golang.org/issue/12806 []staticIPEntry{ - {"127.0.0.1", []string{"PreserveMe", "PreserveMe.local"}}, - {"::1", []string{"PreserveMe", "PreserveMe.local"}}, + {"127.0.0.1", []string{"PreserveMe.", "PreserveMe.local."}}, + {"::1", []string{"PreserveMe.", "PreserveMe.local."}}, }, }, } @@ -209,7 +211,7 @@ func TestLookupStaticAddr(t *testing.T) { func testStaticAddr(t *testing.T, ent staticIPEntry, h *Hostsfile) { hosts := h.LookupStaticAddr(ent.in) for i := range ent.out { - ent.out[i] = absDomainName(ent.out[i]) + ent.out[i] = plugin.Name(ent.out[i]).Normalize() } if !reflect.DeepEqual(hosts, ent.out) { t.Errorf("%s, lookupStaticAddr(%s) = %v; want %v", h.path, ent.in, hosts, h) @@ -221,7 +223,7 @@ func TestHostCacheModification(t *testing.T) { // See https://github.com/golang/go/issues/14212. h := testHostsfile(ipv4hosts) - ent := staticHostEntry{"localhost", []string{"127.0.0.1", "127.0.0.2", "127.0.0.3"}, []string{}} + ent := staticHostEntry{"localhost.", []string{"127.0.0.1", "127.0.0.2", "127.0.0.3"}, []string{}} testStaticHost(t, ent, h) // Modify the addresses return by lookupStaticHost. addrs := h.LookupStaticHostV6(ent.in) @@ -231,7 +233,7 @@ func TestHostCacheModification(t *testing.T) { testStaticHost(t, ent, h) h = testHostsfile(ipv6hosts) - entip := staticIPEntry{"::1", []string{"localhost"}} + entip := staticIPEntry{"::1", []string{"localhost."}} testStaticAddr(t, entip, h) // Modify the hosts return by lookupStaticAddr. hosts := h.LookupStaticAddr(entip.in) diff --git a/plugin/hosts/setup.go b/plugin/hosts/setup.go index 26c3c82d3..73fd3cec4 100644 --- a/plugin/hosts/setup.go +++ b/plugin/hosts/setup.go @@ -26,7 +26,7 @@ func init() { func periodicHostsUpdate(h *Hosts) chan bool { parseChan := make(chan bool) - if h.options.reload == durationOf0s { + if h.options.reload == 0 { return parseChan } @@ -78,7 +78,7 @@ func hostsParse(c *caddy.Controller) (Hosts, error) { h := Hosts{ Hostsfile: &Hostsfile{ path: "/etc/hosts", - hmap: newHostsMap(), + hmap: newMap(), options: options, }, } @@ -152,7 +152,7 @@ func hostsParse(c *caddy.Controller) (Hosts, error) { if err != nil { return h, c.Errf("invalid duration for reload '%s'", remaining[0]) } - if reload < durationOf0s { + if reload < 0 { return h, c.Errf("invalid negative duration for reload '%s'", remaining[0]) } options.reload = reload diff --git a/plugin/hosts/setup_test.go b/plugin/hosts/setup_test.go index 0e3800112..fd8a8060e 100644 --- a/plugin/hosts/setup_test.go +++ b/plugin/hosts/setup_test.go @@ -100,7 +100,7 @@ func TestHostsInlineParse(t *testing.T) { tests := []struct { inputFileRules string shouldErr bool - expectedbyAddr map[string][]string + expectedaddr map[string][]string expectedFallthrough fall.F }{ { @@ -148,19 +148,20 @@ func TestHostsInlineParse(t *testing.T) { t.Fatalf("Test %d expected no errors, but got '%v'", i, err) } else if !test.shouldErr { if !h.Fall.Equal(test.expectedFallthrough) { - t.Fatalf("Test %d expected fallthrough of %v, got %v", i, test.expectedFallthrough, h.Fall) + t.Errorf("Test %d expected fallthrough of %v, got %v", i, test.expectedFallthrough, h.Fall) } - for k, expectedVal := range test.expectedbyAddr { - if val, ok := h.hmap.byAddr[k]; !ok { - t.Fatalf("Test %d expected %v, got no entry", i, k) - } else { - if len(expectedVal) != len(val) { - t.Fatalf("Test %d expected %v records for %v, got %v", i, len(expectedVal), k, len(val)) - } - for j := range expectedVal { - if expectedVal[j] != val[j] { - t.Fatalf("Test %d expected %v for %v, got %v", i, expectedVal[j], j, val[j]) - } + for k, expectedVal := range test.expectedaddr { + val, ok := h.inline.addr[k] + if !ok { + t.Errorf("Test %d expected %v, got no entry", i, k) + continue + } + if len(expectedVal) != len(val) { + t.Errorf("Test %d expected %v records for %v, got %v", i, len(expectedVal), k, len(val)) + } + for j := range expectedVal { + if expectedVal[j] != val[j] { + t.Errorf("Test %d expected %v for %v, got %v", i, expectedVal[j], j, val[j]) } } } |