From ea46134d0480c0d7ef8f9f8d9c461185b625397e Mon Sep 17 00:00:00 2001 From: Andreas Kruger Date: Wed, 15 May 2019 13:40:11 +0200 Subject: [PATCH] Upgrade CoreDNS to 1.5.0 --- Gopkg.lock | 4 +- Gopkg.toml | 2 +- .../coredns/coredns/.github/CONTRIBUTING.md | 1 + .../coredns/coredns/core/dnsserver/address.go | 11 +- .../coredns/coredns/core/dnsserver/config.go | 2 +- .../coredns/core/dnsserver/listen_go111.go | 1 + .../coredns/coredns/core/dnsserver/server.go | 128 +++--- .../coredns/core/dnsserver/server_grpc.go | 15 +- .../coredns/core/dnsserver/server_https.go | 8 + .../coredns/coredns/core/dnsserver/watch.go | 18 - .../coredns/core/dnsserver/zdirectives.go | 5 +- .../coredns/coredns/coremain/run.go | 19 +- .../coredns/coredns/coremain/version.go | 2 +- vendor/github.com/coredns/coredns/pb/Makefile | 8 +- .../github.com/coredns/coredns/pb/dns.pb.go | 379 +++--------------- .../github.com/coredns/coredns/pb/dns.proto | 37 -- .../coredns/coredns/plugin/backend.go | 8 +- .../coredns/coredns/plugin/backend_lookup.go | 115 +++--- .../coredns/coredns/plugin/cache/README.md | 7 +- .../coredns/coredns/plugin/cache/cache.go | 2 +- .../github.com/coredns/coredns/plugin/done.go | 14 + .../coredns/coredns/plugin/errors/README.md | 2 +- .../coredns/coredns/plugin/errors/errors.go | 17 +- .../coredns/coredns/plugin/etcd/msg/path.go | 2 +- .../coredns/plugin/etcd/msg/service.go | 21 +- .../coredns/coredns/plugin/forward/README.md | 23 +- .../coredns/coredns/plugin/forward/connect.go | 33 +- .../coredns/coredns/plugin/forward/dnstap.go | 61 +++ .../coredns/coredns/plugin/forward/forward.go | 15 +- .../coredns/coredns/plugin/forward/lookup.go | 89 ---- .../coredns/plugin/forward/persistent.go | 12 +- .../coredns/coredns/plugin/forward/proxy.go | 4 +- .../coredns/plugin/forward/truncated.go | 29 -- .../coredns/coredns/plugin/health/README.md | 39 +- .../coredns/coredns/plugin/health/health.go | 28 +- .../coredns/coredns/plugin/health/healther.go | 36 -- .../coredns/coredns/plugin/health/setup.go | 27 -- .../coredns/coredns/plugin/log/README.md | 28 +- .../coredns/coredns/plugin/log/log.go | 40 +- .../coredns/coredns/plugin/log/setup.go | 66 +-- .../coredns/coredns/plugin/loop/README.md | 56 +-- .../coredns/coredns/plugin/loop/loop.go | 15 +- .../coredns/coredns/plugin/loop/setup.go | 1 + .../coredns/coredns/plugin/metrics/README.md | 8 +- .../coredns/coredns/plugin/metrics/context.go | 10 +- .../coredns/coredns/plugin/metrics/handler.go | 2 +- .../coredns/coredns/plugin/metrics/metrics.go | 12 +- .../coredns/coredns/plugin/metrics/setup.go | 18 + .../coredns/plugin/metrics/vars/report.go | 55 +-- .../coredns/plugin/metrics/vars/vars.go | 6 + .../coredns/coredns/plugin/normalize.go | 4 +- .../coredns/coredns/plugin/pkg/edns/edns.go | 28 ++ .../coredns/coredns/plugin/pkg/log/log.go | 2 +- .../coredns/coredns/plugin/pkg/log/plugin.go | 11 +- .../coredns/plugin/pkg/replacer/replacer.go | 186 +++++---- .../coredns/coredns/plugin/pkg/up/up.go | 24 +- .../coredns/coredns/plugin/pkg/watch/watch.go | 23 -- .../coredns/plugin/pkg/watch/watcher.go | 178 -------- .../coredns/coredns/plugin/plugin.go | 5 +- .../coredns/coredns/plugin/reload/README.md | 7 + .../coredns/coredns/plugin/reload/reload.go | 44 +- .../coredns/coredns/plugin/reload/setup.go | 11 +- .../coredns/coredns/plugin/test/helpers.go | 125 +++--- .../coredns/coredns/plugin/test/scrape.go | 266 ++++++++++++ .../coredns/coredns/request/edns0.go | 31 ++ .../coredns/coredns/request/request.go | 55 +-- .../coredns/coredns/request/writer.go | 4 +- 67 files changed, 1135 insertions(+), 1410 deletions(-) create mode 120000 vendor/github.com/coredns/coredns/.github/CONTRIBUTING.md delete mode 100644 vendor/github.com/coredns/coredns/core/dnsserver/watch.go create mode 100644 vendor/github.com/coredns/coredns/plugin/done.go create mode 100644 vendor/github.com/coredns/coredns/plugin/forward/dnstap.go delete mode 100644 vendor/github.com/coredns/coredns/plugin/forward/lookup.go delete mode 100644 vendor/github.com/coredns/coredns/plugin/forward/truncated.go delete mode 100644 vendor/github.com/coredns/coredns/plugin/health/healther.go delete mode 100644 vendor/github.com/coredns/coredns/plugin/pkg/watch/watch.go delete mode 100644 vendor/github.com/coredns/coredns/plugin/pkg/watch/watcher.go create mode 100644 vendor/github.com/coredns/coredns/plugin/test/scrape.go create mode 100644 vendor/github.com/coredns/coredns/request/edns0.go diff --git a/Gopkg.lock b/Gopkg.lock index c0874e295..35d25b6e2 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -76,8 +76,8 @@ "request", ] pruneopts = "UT" - revision = "756749c5cad4cd40453b82f70592bc19bb9ccb15" - version = "v1.2.6" + revision = "e3f9a80b1d5a112907a012acee276e9080b32852" + version = "v1.5.0" [[projects]] digest = "1:d2bf3686993c6674049180c5b3c608ceeae8fe99df6b9675594306fba9373b77" diff --git a/Gopkg.toml b/Gopkg.toml index c8961f697..767783241 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -79,7 +79,7 @@ [[constraint]] name = "github.com/coredns/coredns" - version = "v1.2.6" + version = "v1.5.0" [[override]] name = "github.com/ugorji/go" diff --git a/vendor/github.com/coredns/coredns/.github/CONTRIBUTING.md b/vendor/github.com/coredns/coredns/.github/CONTRIBUTING.md new file mode 120000 index 000000000..44fcc6343 --- /dev/null +++ b/vendor/github.com/coredns/coredns/.github/CONTRIBUTING.md @@ -0,0 +1 @@ +../CONTRIBUTING.md \ No newline at end of file diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/address.go b/vendor/github.com/coredns/coredns/core/dnsserver/address.go index 5d3d2b393..1a69c33b8 100644 --- a/vendor/github.com/coredns/coredns/core/dnsserver/address.go +++ b/vendor/github.com/coredns/coredns/core/dnsserver/address.go @@ -20,7 +20,7 @@ type zoneAddr struct { Address string // used for bound zoneAddr - validation of overlapping } -// String return the string representation of z. +// String returns the string representation of z. func (z zoneAddr) String() string { s := z.Transport + "://" + z.Zone + ":" + z.Port if z.Address != "" { @@ -29,13 +29,10 @@ func (z zoneAddr) String() string { return s } -// normalizeZone parses an zone string into a structured format with separate +// normalizeZone parses a zone string into a structured format with separate // host, and port portions, as well as the original input string. func normalizeZone(str string) (zoneAddr, error) { - var err error - - var trans string - trans, str = parse.Transport(str) + trans, str := parse.Transport(str) host, port, ipnet, err := plugin.SplitHostPort(str) if err != nil { @@ -75,7 +72,7 @@ func SplitProtocolHostPort(address string) (protocol string, ip string, port str type zoneOverlap struct { registeredAddr map[zoneAddr]zoneAddr // each zoneAddr is registered once by its key - unboundOverlap map[zoneAddr]zoneAddr // the "no bind" equiv ZoneAdddr is registered by its original key + unboundOverlap map[zoneAddr]zoneAddr // the "no bind" equiv ZoneAddr is registered by its original key } func newOverlapZone() *zoneOverlap { diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/config.go b/vendor/github.com/coredns/coredns/core/dnsserver/config.go index a63058d43..811d39426 100644 --- a/vendor/github.com/coredns/coredns/core/dnsserver/config.go +++ b/vendor/github.com/coredns/coredns/core/dnsserver/config.go @@ -21,7 +21,7 @@ type Config struct { // The port to listen on. Port string - // Root points to a base directory we we find user defined "things". + // Root points to a base directory we find user defined "things". // First consumer is the file plugin to looks for zone files in this place. Root string diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/listen_go111.go b/vendor/github.com/coredns/coredns/core/dnsserver/listen_go111.go index d71c9292b..573988b33 100644 --- a/vendor/github.com/coredns/coredns/core/dnsserver/listen_go111.go +++ b/vendor/github.com/coredns/coredns/core/dnsserver/listen_go111.go @@ -9,6 +9,7 @@ import ( "syscall" "github.com/coredns/coredns/plugin/pkg/log" + "golang.org/x/sys/unix" ) diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/server.go b/vendor/github.com/coredns/coredns/core/dnsserver/server.go index 5ca826b0a..c55f4db5f 100644 --- a/vendor/github.com/coredns/coredns/core/dnsserver/server.go +++ b/vendor/github.com/coredns/coredns/core/dnsserver/server.go @@ -33,12 +33,12 @@ type Server struct { server [2]*dns.Server // 0 is a net.Listener, 1 is a net.PacketConn (a *UDPConn) in our case. m sync.Mutex // protects the servers - zones map[string]*Config // zones keyed by their address - dnsWg sync.WaitGroup // used to wait on outstanding connections - connTimeout time.Duration // the maximum duration of a graceful shutdown - trace trace.Trace // the trace plugin for the server - debug bool // disable recover() - classChaos bool // allow non-INET class queries + zones map[string]*Config // zones keyed by their address + dnsWg sync.WaitGroup // used to wait on outstanding connections + graceTimeout time.Duration // the maximum duration of a graceful shutdown + trace trace.Trace // the trace plugin for the server + debug bool // disable recover() + classChaos bool // allow non-INET class queries } // NewServer returns a new CoreDNS server and compiles all plugins in to it. By default CH class @@ -46,9 +46,9 @@ type Server struct { func NewServer(addr string, group []*Config) (*Server, error) { s := &Server{ - Addr: addr, - zones: make(map[string]*Config), - connTimeout: 5 * time.Second, // TODO(miek): was configurable + Addr: addr, + zones: make(map[string]*Config), + graceTimeout: 5 * time.Second, } // We have to bound our wg with one increment @@ -66,22 +66,8 @@ func NewServer(addr string, group []*Config) (*Server, error) { } // set the config per zone s.zones[site.Zone] = site + // compile custom plugin for everything - if site.registry != nil { - // this config is already computed with the chain of plugin - // set classChaos in accordance with previously registered plugins - for name := range enableChaos { - if _, ok := site.registry[name]; ok { - s.classChaos = true - break - } - } - // set trace handler in accordance with previously registered "trace" plugin - if handler, ok := site.registry["trace"]; ok { - s.trace = handler.(trace.Trace) - } - continue - } var stack plugin.Handler for i := len(site.Plugin) - 1; i >= 0; i-- { stack = site.Plugin[i](stack) @@ -97,7 +83,7 @@ func NewServer(addr string, group []*Config) (*Server, error) { } } // Unblock CH class queries when any of these plugins are loaded. - if _, ok := enableChaos[stack.Name()]; ok { + if _, ok := EnableChaos[stack.Name()]; ok { s.classChaos = true } } @@ -142,6 +128,11 @@ func (s *Server) Listen() (net.Listener, error) { return l, nil } +// WrapListener Listen implements caddy.GracefulServer interface. +func (s *Server) WrapListener(ln net.Listener) net.Listener { + return ln +} + // ListenPacket implements caddy.UDPServer interface. func (s *Server) ListenPacket() (net.PacketConn, error) { p, err := listenPacket("udp", s.Addr[len(transport.DNS+"://"):]) @@ -172,7 +163,7 @@ func (s *Server) Stop() (err error) { // Wait for remaining connections to finish or // force them all to close after timeout select { - case <-time.After(s.connTimeout): + case <-time.After(s.graceTimeout): case <-done: } } @@ -200,7 +191,7 @@ func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) // The default dns.Mux checks the question section size, but we have our // own mux here. Check if we have a question section. If not drop them here. if r == nil || len(r.Question) == 0 { - DefaultErrorFunc(ctx, w, r, dns.RcodeServerFailure) + errorAndMetricsFunc(s.Addr, w, r, dns.RcodeServerFailure) return } @@ -210,13 +201,13 @@ func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) // need to make sure that we stay alive up here if rec := recover(); rec != nil { vars.Panic.Inc() - DefaultErrorFunc(ctx, w, r, dns.RcodeServerFailure) + errorAndMetricsFunc(s.Addr, w, r, dns.RcodeServerFailure) } }() } if !s.classChaos && r.Question[0].Qclass != dns.ClassINET { - DefaultErrorFunc(ctx, w, r, dns.RcodeRefused) + errorAndMetricsFunc(s.Addr, w, r, dns.RcodeRefused) return } @@ -225,12 +216,6 @@ func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) return } - ctx, err := incrementDepthAndCheck(ctx) - if err != nil { - DefaultErrorFunc(ctx, w, r, dns.RcodeServerFailure) - return - } - q := r.Question[0].Name b := make([]byte, len(q)) var off int @@ -252,16 +237,11 @@ func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) } if h, ok := s.zones[string(b[:l])]; ok { - - // Set server's address in the context so plugins can reference back to this, - // This will makes those metrics unique. - ctx = context.WithValue(ctx, plugin.ServerCtx{}, s.Addr) - if r.Question[0].Qtype != dns.TypeDS { if h.FilterFunc == nil { rcode, _ := h.pluginChain.ServeDNS(ctx, w, r) if !plugin.ClientWrite(rcode) { - DefaultErrorFunc(ctx, w, r, rcode) + errorFunc(s.Addr, w, r, rcode) } return } @@ -270,7 +250,7 @@ func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) if h.FilterFunc(q) { rcode, _ := h.pluginChain.ServeDNS(ctx, w, r) if !plugin.ClientWrite(rcode) { - DefaultErrorFunc(ctx, w, r, rcode) + errorFunc(s.Addr, w, r, rcode) } return } @@ -292,26 +272,22 @@ func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) // DS request, and we found a zone, use the handler for the query. rcode, _ := dshandler.pluginChain.ServeDNS(ctx, w, r) if !plugin.ClientWrite(rcode) { - DefaultErrorFunc(ctx, w, r, rcode) + errorFunc(s.Addr, w, r, rcode) } return } // Wildcard match, if we have found nothing try the root zone as a last resort. if h, ok := s.zones["."]; ok && h.pluginChain != nil { - - // See comment above. - ctx = context.WithValue(ctx, plugin.ServerCtx{}, s.Addr) - rcode, _ := h.pluginChain.ServeDNS(ctx, w, r) if !plugin.ClientWrite(rcode) { - DefaultErrorFunc(ctx, w, r, rcode) + errorFunc(s.Addr, w, r, rcode) } return } // Still here? Error out with REFUSED. - DefaultErrorFunc(ctx, w, r, dns.RcodeRefused) + errorAndMetricsFunc(s.Addr, w, r, dns.RcodeRefused) } // OnStartupComplete lists the sites served by this server @@ -337,56 +313,42 @@ func (s *Server) Tracer() ot.Tracer { return s.trace.Tracer() } -// DefaultErrorFunc responds to an DNS request with an error. -func DefaultErrorFunc(ctx context.Context, w dns.ResponseWriter, r *dns.Msg, rc int) { +// errorFunc responds to an DNS request with an error. +func errorFunc(server string, w dns.ResponseWriter, r *dns.Msg, rc int) { state := request.Request{W: w, Req: r} answer := new(dns.Msg) answer.SetRcode(r, rc) - state.SizeAndDo(answer) - vars.Report(ctx, state, vars.Dropped, rcode.ToString(rc), answer.Len(), time.Now()) - w.WriteMsg(answer) } -// incrementDepthAndCheck increments the loop counter in the context, and returns an error if -// the counter exceeds the max number of re-entries -func incrementDepthAndCheck(ctx context.Context) (context.Context, error) { - // Loop counter for self directed lookups - loop := ctx.Value(loopKey{}) - if loop == nil { - ctx = context.WithValue(ctx, loopKey{}, 0) - return ctx, nil - } +func errorAndMetricsFunc(server string, w dns.ResponseWriter, r *dns.Msg, rc int) { + state := request.Request{W: w, Req: r} - iloop := loop.(int) + 1 - if iloop > maxreentries { - return ctx, fmt.Errorf("too deep") - } - ctx = context.WithValue(ctx, loopKey{}, iloop) - return ctx, nil + answer := new(dns.Msg) + answer.SetRcode(r, rc) + state.SizeAndDo(answer) + + vars.Report(server, state, vars.Dropped, rcode.ToString(rc), answer.Len(), time.Now()) + + w.WriteMsg(answer) } const ( - tcp = 0 - udp = 1 - maxreentries = 10 + tcp = 0 + udp = 1 ) -type ( - // Key is the context key for the current server - Key struct{} - loopKey struct{} // loopKey is the context key for counting self loops -) +// Key is the context key for the current server added to the context. +type Key struct{} -// enableChaos is a map with plugin names for which we should open CH class queries as -// we block these by default. -var enableChaos = map[string]bool{ - "chaos": true, - "forward": true, - "proxy": true, +// EnableChaos is a map with plugin names for which we should open CH class queries as we block these by default. +var EnableChaos = map[string]struct{}{ + "chaos": struct{}{}, + "forward": struct{}{}, + "proxy": struct{}{}, } // Quiet mode will not show any informative output on initialization. diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/server_grpc.go b/vendor/github.com/coredns/coredns/core/dnsserver/server_grpc.go index 7de36a5fd..e26eaebfb 100644 --- a/vendor/github.com/coredns/coredns/core/dnsserver/server_grpc.go +++ b/vendor/github.com/coredns/coredns/core/dnsserver/server_grpc.go @@ -9,7 +9,6 @@ import ( "github.com/coredns/coredns/pb" "github.com/coredns/coredns/plugin/pkg/transport" - "github.com/coredns/coredns/plugin/pkg/watch" "github.com/grpc-ecosystem/grpc-opentracing/go/otgrpc" "github.com/miekg/dns" @@ -24,7 +23,6 @@ type ServergRPC struct { grpcServer *grpc.Server listenAddr net.Addr tlsConfig *tls.Config - watch watch.Watcher } // NewServergRPC returns a new CoreDNS GRPC server and compiles all plugin in to it. @@ -41,7 +39,7 @@ func NewServergRPC(addr string, group []*Config) (*ServergRPC, error) { tlsConfig = conf.TLSConfig } - return &ServergRPC{Server: s, tlsConfig: tlsConfig, watch: watch.NewWatcher(watchables(s.zones))}, nil + return &ServergRPC{Server: s, tlsConfig: tlsConfig}, nil } // Serve implements caddy.TCPServer interface. @@ -103,9 +101,6 @@ func (s *ServergRPC) OnStartupComplete() { func (s *ServergRPC) Stop() (err error) { s.m.Lock() defer s.m.Unlock() - if s.watch != nil { - s.watch.Stop() - } if s.grpcServer != nil { s.grpcServer.GracefulStop() } @@ -144,12 +139,6 @@ func (s *ServergRPC) Query(ctx context.Context, in *pb.DnsPacket) (*pb.DnsPacket return &pb.DnsPacket{Msg: packed}, nil } -// Watch is the entrypoint called by the gRPC layer when the user asks -// to watch a query. -func (s *ServergRPC) Watch(stream pb.DnsService_WatchServer) error { - return s.watch.Watch(stream) -} - // Shutdown stops the server (non gracefully). func (s *ServergRPC) Shutdown() error { if s.grpcServer != nil { @@ -165,7 +154,7 @@ type gRPCresponse struct { } // Write is the hack that makes this work. It does not actually write the message -// but returns the bytes we need to to write in r. We can then pick this up in Query +// but returns the bytes we need to write in r. We can then pick this up in Query // and write a proper protobuf back to the client. func (r *gRPCresponse) Write(b []byte) (int, error) { r.Msg = new(dns.Msg) diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/server_https.go b/vendor/github.com/coredns/coredns/core/dnsserver/server_https.go index 1e184e044..6ae6ce6a6 100644 --- a/vendor/github.com/coredns/coredns/core/dnsserver/server_https.go +++ b/vendor/github.com/coredns/coredns/core/dnsserver/server_https.go @@ -119,6 +119,14 @@ func (s *ServerHTTPS) ServeHTTP(w http.ResponseWriter, r *http.Request) { // We should expect a packet to be returned that we can send to the client. s.ServeDNS(context.Background(), dw, msg) + // See section 4.2.1 of RFC 8484. + // We are using code 500 to indicate an unexpected situation when the chain + // handler has not provided any response message. + if dw.Msg == nil { + http.Error(w, "No response", http.StatusInternalServerError) + return + } + buf, _ := dw.Msg.Pack() mt, _ := response.Typify(dw.Msg, time.Now().UTC()) diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/watch.go b/vendor/github.com/coredns/coredns/core/dnsserver/watch.go deleted file mode 100644 index 590bac144..000000000 --- a/vendor/github.com/coredns/coredns/core/dnsserver/watch.go +++ /dev/null @@ -1,18 +0,0 @@ -package dnsserver - -import ( - "github.com/coredns/coredns/plugin/pkg/watch" -) - -func watchables(zones map[string]*Config) []watch.Watchable { - var w []watch.Watchable - for _, config := range zones { - plugins := config.Handlers() - for _, p := range plugins { - if x, ok := p.(watch.Watchable); ok { - w = append(w, x) - } - } - } - return w -} diff --git a/vendor/github.com/coredns/coredns/core/dnsserver/zdirectives.go b/vendor/github.com/coredns/coredns/core/dnsserver/zdirectives.go index 280c03144..0420672f0 100644 --- a/vendor/github.com/coredns/coredns/core/dnsserver/zdirectives.go +++ b/vendor/github.com/coredns/coredns/core/dnsserver/zdirectives.go @@ -11,6 +11,7 @@ package dnsserver // care what plugin above them are doing. var Directives = []string{ "metadata", + "cancel", "tls", "reload", "nsid", @@ -18,6 +19,7 @@ var Directives = []string{ "bind", "debug", "trace", + "ready", "health", "pprof", "prometheus", @@ -34,6 +36,7 @@ var Directives = []string{ "hosts", "route53", "federation", + "k8s_external", "kubernetes", "file", "auto", @@ -41,7 +44,7 @@ var Directives = []string{ "etcd", "loop", "forward", - "proxy", + "grpc", "erratic", "whoami", "on", diff --git a/vendor/github.com/coredns/coredns/coremain/run.go b/vendor/github.com/coredns/coredns/coremain/run.go index 63ac6f354..1c7e475ee 100644 --- a/vendor/github.com/coredns/coredns/coremain/run.go +++ b/vendor/github.com/coredns/coredns/coremain/run.go @@ -95,9 +95,6 @@ func Run() { showVersion() } - // Execute instantiation events - caddy.EmitEvent(caddy.InstanceStartupEvent, instance) - // Twiddle your thumbs instance.Wait() } @@ -257,14 +254,14 @@ var ( ) // flagsBlacklist removes flags with these names from our flagset. -var flagsBlacklist = map[string]bool{ - "logtostderr": true, - "alsologtostderr": true, - "v": true, - "stderrthreshold": true, - "vmodule": true, - "log_backtrace_at": true, - "log_dir": true, +var flagsBlacklist = map[string]struct{}{ + "logtostderr": struct{}{}, + "alsologtostderr": struct{}{}, + "v": struct{}{}, + "stderrthreshold": struct{}{}, + "vmodule": struct{}{}, + "log_backtrace_at": struct{}{}, + "log_dir": struct{}{}, } var flagsToKeep []*flag.Flag diff --git a/vendor/github.com/coredns/coredns/coremain/version.go b/vendor/github.com/coredns/coredns/coremain/version.go index ae274821d..d0ac1dae0 100644 --- a/vendor/github.com/coredns/coredns/coremain/version.go +++ b/vendor/github.com/coredns/coredns/coremain/version.go @@ -2,7 +2,7 @@ package coremain // Various CoreDNS constants. const ( - CoreVersion = "1.2.6" + CoreVersion = "1.5.0" coreName = "CoreDNS" serverType = "dns" ) diff --git a/vendor/github.com/coredns/coredns/pb/Makefile b/vendor/github.com/coredns/coredns/pb/Makefile index bdfc8e3b0..a666d6c15 100644 --- a/vendor/github.com/coredns/coredns/pb/Makefile +++ b/vendor/github.com/coredns/coredns/pb/Makefile @@ -6,6 +6,8 @@ all: dns.pb.go dns.pb.go: dns.proto - protoc --go_out=plugins=grpc:. dns.proto && \ - sed -e s?golang.org/x/net/context?context? < dns.pb.go > dns.pb.go.tmp && \ - mv dns.pb.go.tmp dns.pb.go + protoc --go_out=plugins=grpc:. dns.proto + +.PHONY: clean +clean: + rm dns.pb.go diff --git a/vendor/github.com/coredns/coredns/pb/dns.pb.go b/vendor/github.com/coredns/coredns/pb/dns.pb.go index d79e24f6d..919f0e7d7 100644 --- a/vendor/github.com/coredns/coredns/pb/dns.pb.go +++ b/vendor/github.com/coredns/coredns/pb/dns.pb.go @@ -1,27 +1,14 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // source: dns.proto -/* -Package pb is a generated protocol buffer package. - -It is generated from these files: - dns.proto - -It has these top-level messages: - DnsPacket - WatchRequest - WatchCreateRequest - WatchCancelRequest - WatchResponse -*/ package pb -import proto "github.com/golang/protobuf/proto" -import fmt "fmt" -import math "math" - import ( context "context" + fmt "fmt" + math "math" + + proto "github.com/golang/protobuf/proto" grpc "google.golang.org/grpc" ) @@ -30,245 +17,70 @@ var _ = proto.Marshal var _ = fmt.Errorf var _ = math.Inf +/* Miek: disabled this manually, because I don't know what the heck */ +/* // This is a compile-time assertion to ensure that this generated file // is compatible with the proto package it is being compiled against. // A compilation error at this line likely means your copy of the // proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion2 // please upgrade the proto package +const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +*/ type DnsPacket struct { - Msg []byte `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` + Msg []byte `protobuf:"bytes,1,opt,name=msg,proto3" json:"msg,omitempty"` + XXX_NoUnkeyedLiteral struct{} `json:"-"` + XXX_unrecognized []byte `json:"-"` + XXX_sizecache int32 `json:"-"` } -func (m *DnsPacket) Reset() { *m = DnsPacket{} } -func (m *DnsPacket) String() string { return proto.CompactTextString(m) } -func (*DnsPacket) ProtoMessage() {} -func (*DnsPacket) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{0} } - -func (m *DnsPacket) GetMsg() []byte { - if m != nil { - return m.Msg - } - return nil +func (m *DnsPacket) Reset() { *m = DnsPacket{} } +func (m *DnsPacket) String() string { return proto.CompactTextString(m) } +func (*DnsPacket) ProtoMessage() {} +func (*DnsPacket) Descriptor() ([]byte, []int) { + return fileDescriptor_638ff8d8aaf3d8ae, []int{0} } -type WatchRequest struct { - // request_union is a request to either create a new watcher or cancel an existing watcher. - // - // Types that are valid to be assigned to RequestUnion: - // *WatchRequest_CreateRequest - // *WatchRequest_CancelRequest - RequestUnion isWatchRequest_RequestUnion `protobuf_oneof:"request_union"` +func (m *DnsPacket) XXX_Unmarshal(b []byte) error { + return xxx_messageInfo_DnsPacket.Unmarshal(m, b) } - -func (m *WatchRequest) Reset() { *m = WatchRequest{} } -func (m *WatchRequest) String() string { return proto.CompactTextString(m) } -func (*WatchRequest) ProtoMessage() {} -func (*WatchRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{1} } - -type isWatchRequest_RequestUnion interface { - isWatchRequest_RequestUnion() -} - -type WatchRequest_CreateRequest struct { - CreateRequest *WatchCreateRequest `protobuf:"bytes,1,opt,name=create_request,json=createRequest,oneof"` +func (m *DnsPacket) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { + return xxx_messageInfo_DnsPacket.Marshal(b, m, deterministic) } -type WatchRequest_CancelRequest struct { - CancelRequest *WatchCancelRequest `protobuf:"bytes,2,opt,name=cancel_request,json=cancelRequest,oneof"` +func (m *DnsPacket) XXX_Merge(src proto.Message) { + xxx_messageInfo_DnsPacket.Merge(m, src) } - -func (*WatchRequest_CreateRequest) isWatchRequest_RequestUnion() {} -func (*WatchRequest_CancelRequest) isWatchRequest_RequestUnion() {} - -func (m *WatchRequest) GetRequestUnion() isWatchRequest_RequestUnion { - if m != nil { - return m.RequestUnion - } - return nil +func (m *DnsPacket) XXX_Size() int { + return xxx_messageInfo_DnsPacket.Size(m) } - -func (m *WatchRequest) GetCreateRequest() *WatchCreateRequest { - if x, ok := m.GetRequestUnion().(*WatchRequest_CreateRequest); ok { - return x.CreateRequest - } - return nil +func (m *DnsPacket) XXX_DiscardUnknown() { + xxx_messageInfo_DnsPacket.DiscardUnknown(m) } -func (m *WatchRequest) GetCancelRequest() *WatchCancelRequest { - if x, ok := m.GetRequestUnion().(*WatchRequest_CancelRequest); ok { - return x.CancelRequest - } - return nil -} +var xxx_messageInfo_DnsPacket proto.InternalMessageInfo -// XXX_OneofFuncs is for the internal use of the proto package. -func (*WatchRequest) XXX_OneofFuncs() (func(msg proto.Message, b *proto.Buffer) error, func(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error), func(msg proto.Message) (n int), []interface{}) { - return _WatchRequest_OneofMarshaler, _WatchRequest_OneofUnmarshaler, _WatchRequest_OneofSizer, []interface{}{ - (*WatchRequest_CreateRequest)(nil), - (*WatchRequest_CancelRequest)(nil), - } -} - -func _WatchRequest_OneofMarshaler(msg proto.Message, b *proto.Buffer) error { - m := msg.(*WatchRequest) - // request_union - switch x := m.RequestUnion.(type) { - case *WatchRequest_CreateRequest: - b.EncodeVarint(1<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.CreateRequest); err != nil { - return err - } - case *WatchRequest_CancelRequest: - b.EncodeVarint(2<<3 | proto.WireBytes) - if err := b.EncodeMessage(x.CancelRequest); err != nil { - return err - } - case nil: - default: - return fmt.Errorf("WatchRequest.RequestUnion has unexpected type %T", x) - } - return nil -} - -func _WatchRequest_OneofUnmarshaler(msg proto.Message, tag, wire int, b *proto.Buffer) (bool, error) { - m := msg.(*WatchRequest) - switch tag { - case 1: // request_union.create_request - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(WatchCreateRequest) - err := b.DecodeMessage(msg) - m.RequestUnion = &WatchRequest_CreateRequest{msg} - return true, err - case 2: // request_union.cancel_request - if wire != proto.WireBytes { - return true, proto.ErrInternalBadWireType - } - msg := new(WatchCancelRequest) - err := b.DecodeMessage(msg) - m.RequestUnion = &WatchRequest_CancelRequest{msg} - return true, err - default: - return false, nil - } -} - -func _WatchRequest_OneofSizer(msg proto.Message) (n int) { - m := msg.(*WatchRequest) - // request_union - switch x := m.RequestUnion.(type) { - case *WatchRequest_CreateRequest: - s := proto.Size(x.CreateRequest) - n += proto.SizeVarint(1<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s - case *WatchRequest_CancelRequest: - s := proto.Size(x.CancelRequest) - n += proto.SizeVarint(2<<3 | proto.WireBytes) - n += proto.SizeVarint(uint64(s)) - n += s - case nil: - default: - panic(fmt.Sprintf("proto: unexpected type %T in oneof", x)) - } - return n -} - -type WatchCreateRequest struct { - Query *DnsPacket `protobuf:"bytes,1,opt,name=query" json:"query,omitempty"` -} - -func (m *WatchCreateRequest) Reset() { *m = WatchCreateRequest{} } -func (m *WatchCreateRequest) String() string { return proto.CompactTextString(m) } -func (*WatchCreateRequest) ProtoMessage() {} -func (*WatchCreateRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{2} } - -func (m *WatchCreateRequest) GetQuery() *DnsPacket { +func (m *DnsPacket) GetMsg() []byte { if m != nil { - return m.Query + return m.Msg } return nil } -type WatchCancelRequest struct { - // watch_id is the watcher id to cancel - WatchId int64 `protobuf:"varint,1,opt,name=watch_id,json=watchId" json:"watch_id,omitempty"` -} - -func (m *WatchCancelRequest) Reset() { *m = WatchCancelRequest{} } -func (m *WatchCancelRequest) String() string { return proto.CompactTextString(m) } -func (*WatchCancelRequest) ProtoMessage() {} -func (*WatchCancelRequest) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{3} } - -func (m *WatchCancelRequest) GetWatchId() int64 { - if m != nil { - return m.WatchId - } - return 0 -} - -type WatchResponse struct { - // watch_id is the ID of the watcher that corresponds to the response. - WatchId int64 `protobuf:"varint,1,opt,name=watch_id,json=watchId" json:"watch_id,omitempty"` - // created is set to true if the response is for a create watch request. - // The client should record the watch_id and expect to receive DNS replies - // from the same stream. - // All replies sent to the created watcher will attach with the same watch_id. - Created bool `protobuf:"varint,2,opt,name=created" json:"created,omitempty"` - // canceled is set to true if the response is for a cancel watch request. - // No further events will be sent to the canceled watcher. - Canceled bool `protobuf:"varint,3,opt,name=canceled" json:"canceled,omitempty"` - Qname string `protobuf:"bytes,4,opt,name=qname" json:"qname,omitempty"` - Err string `protobuf:"bytes,5,opt,name=err" json:"err,omitempty"` -} - -func (m *WatchResponse) Reset() { *m = WatchResponse{} } -func (m *WatchResponse) String() string { return proto.CompactTextString(m) } -func (*WatchResponse) ProtoMessage() {} -func (*WatchResponse) Descriptor() ([]byte, []int) { return fileDescriptor0, []int{4} } - -func (m *WatchResponse) GetWatchId() int64 { - if m != nil { - return m.WatchId - } - return 0 -} - -func (m *WatchResponse) GetCreated() bool { - if m != nil { - return m.Created - } - return false -} - -func (m *WatchResponse) GetCanceled() bool { - if m != nil { - return m.Canceled - } - return false -} - -func (m *WatchResponse) GetQname() string { - if m != nil { - return m.Qname - } - return "" +func init() { + proto.RegisterType((*DnsPacket)(nil), "coredns.dns.DnsPacket") } -func (m *WatchResponse) GetErr() string { - if m != nil { - return m.Err - } - return "" -} +func init() { proto.RegisterFile("dns.proto", fileDescriptor_638ff8d8aaf3d8ae) } -func init() { - proto.RegisterType((*DnsPacket)(nil), "coredns.dns.DnsPacket") - proto.RegisterType((*WatchRequest)(nil), "coredns.dns.WatchRequest") - proto.RegisterType((*WatchCreateRequest)(nil), "coredns.dns.WatchCreateRequest") - proto.RegisterType((*WatchCancelRequest)(nil), "coredns.dns.WatchCancelRequest") - proto.RegisterType((*WatchResponse)(nil), "coredns.dns.WatchResponse") +var fileDescriptor_638ff8d8aaf3d8ae = []byte{ + // 120 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xe2, 0x4c, 0xc9, 0x2b, 0xd6, + 0x2b, 0x28, 0xca, 0x2f, 0xc9, 0x17, 0xe2, 0x4e, 0xce, 0x2f, 0x4a, 0x05, 0x71, 0x53, 0xf2, 0x8a, + 0x95, 0x64, 0xb9, 0x38, 0x5d, 0xf2, 0x8a, 0x03, 0x12, 0x93, 0xb3, 0x53, 0x4b, 0x84, 0x04, 0xb8, + 0x98, 0x73, 0x8b, 0xd3, 0x25, 0x18, 0x15, 0x18, 0x35, 0x78, 0x82, 0x40, 0x4c, 0x23, 0x57, 0x2e, + 0x2e, 0x97, 0xbc, 0xe2, 0xe0, 0xd4, 0xa2, 0xb2, 0xcc, 0xe4, 0x54, 0x21, 0x73, 0x2e, 0xd6, 0xc0, + 0xd2, 0xd4, 0xa2, 0x4a, 0x21, 0x31, 0x3d, 0x24, 0x33, 0xf4, 0xe0, 0x06, 0x48, 0xe1, 0x10, 0x77, + 0x62, 0x89, 0x62, 0x2a, 0x48, 0x4a, 0x62, 0x03, 0xdb, 0x6f, 0x0c, 0x08, 0x00, 0x00, 0xff, 0xff, + 0xf5, 0xd1, 0x3f, 0x26, 0x8c, 0x00, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -279,11 +91,11 @@ var _ grpc.ClientConn // is compatible with the grpc package it is being compiled against. const _ = grpc.SupportPackageIsVersion4 -// Client API for DnsService service - +// DnsServiceClient is the client API for DnsService service. +// +// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream. type DnsServiceClient interface { Query(ctx context.Context, in *DnsPacket, opts ...grpc.CallOption) (*DnsPacket, error) - Watch(ctx context.Context, opts ...grpc.CallOption) (DnsService_WatchClient, error) } type dnsServiceClient struct { @@ -296,49 +108,16 @@ func NewDnsServiceClient(cc *grpc.ClientConn) DnsServiceClient { func (c *dnsServiceClient) Query(ctx context.Context, in *DnsPacket, opts ...grpc.CallOption) (*DnsPacket, error) { out := new(DnsPacket) - err := grpc.Invoke(ctx, "/coredns.dns.DnsService/Query", in, out, c.cc, opts...) + err := c.cc.Invoke(ctx, "/coredns.dns.DnsService/Query", in, out, opts...) if err != nil { return nil, err } return out, nil } -func (c *dnsServiceClient) Watch(ctx context.Context, opts ...grpc.CallOption) (DnsService_WatchClient, error) { - stream, err := grpc.NewClientStream(ctx, &_DnsService_serviceDesc.Streams[0], c.cc, "/coredns.dns.DnsService/Watch", opts...) - if err != nil { - return nil, err - } - x := &dnsServiceWatchClient{stream} - return x, nil -} - -type DnsService_WatchClient interface { - Send(*WatchRequest) error - Recv() (*WatchResponse, error) - grpc.ClientStream -} - -type dnsServiceWatchClient struct { - grpc.ClientStream -} - -func (x *dnsServiceWatchClient) Send(m *WatchRequest) error { - return x.ClientStream.SendMsg(m) -} - -func (x *dnsServiceWatchClient) Recv() (*WatchResponse, error) { - m := new(WatchResponse) - if err := x.ClientStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - -// Server API for DnsService service - +// DnsServiceServer is the server API for DnsService service. type DnsServiceServer interface { Query(context.Context, *DnsPacket) (*DnsPacket, error) - Watch(DnsService_WatchServer) error } func RegisterDnsServiceServer(s *grpc.Server, srv DnsServiceServer) { @@ -363,32 +142,6 @@ func _DnsService_Query_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } -func _DnsService_Watch_Handler(srv interface{}, stream grpc.ServerStream) error { - return srv.(DnsServiceServer).Watch(&dnsServiceWatchServer{stream}) -} - -type DnsService_WatchServer interface { - Send(*WatchResponse) error - Recv() (*WatchRequest, error) - grpc.ServerStream -} - -type dnsServiceWatchServer struct { - grpc.ServerStream -} - -func (x *dnsServiceWatchServer) Send(m *WatchResponse) error { - return x.ServerStream.SendMsg(m) -} - -func (x *dnsServiceWatchServer) Recv() (*WatchRequest, error) { - m := new(WatchRequest) - if err := x.ServerStream.RecvMsg(m); err != nil { - return nil, err - } - return m, nil -} - var _DnsService_serviceDesc = grpc.ServiceDesc{ ServiceName: "coredns.dns.DnsService", HandlerType: (*DnsServiceServer)(nil), @@ -398,40 +151,6 @@ var _DnsService_serviceDesc = grpc.ServiceDesc{ Handler: _DnsService_Query_Handler, }, }, - Streams: []grpc.StreamDesc{ - { - StreamName: "Watch", - Handler: _DnsService_Watch_Handler, - ServerStreams: true, - ClientStreams: true, - }, - }, + Streams: []grpc.StreamDesc{}, Metadata: "dns.proto", } - -func init() { proto.RegisterFile("dns.proto", fileDescriptor0) } - -var fileDescriptor0 = []byte{ - // 333 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x52, 0x41, 0x4f, 0x32, 0x31, - 0x14, 0xfc, 0x0a, 0xec, 0x07, 0x3c, 0x40, 0xcd, 0x8b, 0x31, 0xcb, 0x26, 0x46, 0xb2, 0x27, 0x0e, - 0x06, 0x0d, 0x1e, 0xbc, 0xaf, 0x1c, 0xf0, 0xa6, 0xf5, 0x60, 0xe2, 0x85, 0x2c, 0xdd, 0x17, 0x25, - 0x4a, 0x17, 0xda, 0x45, 0xe3, 0x3f, 0xd0, 0xdf, 0xe3, 0x1f, 0x34, 0xfb, 0xba, 0x90, 0x35, 0x88, - 0xb7, 0xce, 0x74, 0x3a, 0xed, 0xcc, 0x2b, 0x34, 0x13, 0x6d, 0x07, 0x0b, 0x93, 0x66, 0x29, 0xb6, - 0x54, 0x6a, 0x28, 0x87, 0x89, 0xb6, 0xe1, 0x31, 0x34, 0x47, 0xda, 0xde, 0xc4, 0xea, 0x99, 0x32, - 0x3c, 0x80, 0xea, 0xdc, 0x3e, 0xfa, 0xa2, 0x27, 0xfa, 0x6d, 0x99, 0x2f, 0xc3, 0x2f, 0x01, 0xed, - 0xfb, 0x38, 0x53, 0x4f, 0x92, 0x96, 0x2b, 0xb2, 0x19, 0x8e, 0x61, 0x4f, 0x19, 0x8a, 0x33, 0x9a, - 0x18, 0xc7, 0xb0, 0xba, 0x35, 0x3c, 0x19, 0x94, 0x5c, 0x07, 0x7c, 0xe4, 0x8a, 0x75, 0xc5, 0xc1, - 0xf1, 0x3f, 0xd9, 0x51, 0x65, 0x82, 0x9d, 0x62, 0xad, 0xe8, 0x65, 0xe3, 0x54, 0xd9, 0xe9, 0xc4, - 0xba, 0xb2, 0x53, 0x99, 0x88, 0xf6, 0xa1, 0x53, 0x58, 0x4c, 0x56, 0x7a, 0x96, 0xea, 0x30, 0x02, - 0xdc, 0x7e, 0x01, 0x9e, 0x82, 0xb7, 0x5c, 0x91, 0x79, 0x2f, 0x5e, 0x7c, 0xf4, 0xe3, 0x9e, 0x4d, - 0x09, 0xd2, 0x89, 0xc2, 0xb3, 0xb5, 0x47, 0xf9, 0x2a, 0xec, 0x42, 0xe3, 0x2d, 0x67, 0x27, 0xb3, - 0x84, 0x6d, 0xaa, 0xb2, 0xce, 0xf8, 0x3a, 0x09, 0x3f, 0x04, 0x74, 0x8a, 0xaa, 0xec, 0x22, 0xd5, - 0x96, 0xfe, 0x10, 0xa3, 0x0f, 0x75, 0xd7, 0x46, 0xc2, 0xa9, 0x1b, 0x72, 0x0d, 0x31, 0x80, 0x86, - 0x4b, 0x47, 0x89, 0x5f, 0xe5, 0xad, 0x0d, 0xc6, 0x43, 0xf0, 0x96, 0x3a, 0x9e, 0x93, 0x5f, 0xeb, - 0x89, 0x7e, 0x53, 0x3a, 0x90, 0x4f, 0x8d, 0x8c, 0xf1, 0x3d, 0xe6, 0xf2, 0xe5, 0xf0, 0x53, 0x00, - 0x8c, 0xb4, 0xbd, 0x23, 0xf3, 0x3a, 0x53, 0x84, 0x97, 0xe0, 0xdd, 0xe6, 0x99, 0x70, 0x47, 0xe4, - 0x60, 0x07, 0x8f, 0x11, 0x78, 0x9c, 0x08, 0xbb, 0xdb, 0x33, 0x29, 0x1a, 0x09, 0x82, 0xdf, 0xb6, - 0x5c, 0x01, 0x7d, 0x71, 0x2e, 0xa2, 0xda, 0x43, 0x65, 0x31, 0x9d, 0xfe, 0xe7, 0xaf, 0x77, 0xf1, - 0x1d, 0x00, 0x00, 0xff, 0xff, 0xd2, 0x5b, 0x8c, 0xe1, 0x87, 0x02, 0x00, 0x00, -} diff --git a/vendor/github.com/coredns/coredns/pb/dns.proto b/vendor/github.com/coredns/coredns/pb/dns.proto index e4ac2eb2c..8461f01e6 100644 --- a/vendor/github.com/coredns/coredns/pb/dns.proto +++ b/vendor/github.com/coredns/coredns/pb/dns.proto @@ -9,41 +9,4 @@ message DnsPacket { service DnsService { rpc Query (DnsPacket) returns (DnsPacket); - rpc Watch (stream WatchRequest) returns (stream WatchResponse); -} - -message WatchRequest { - // request_union is a request to either create a new watcher or cancel an existing watcher. - oneof request_union { - WatchCreateRequest create_request = 1; - WatchCancelRequest cancel_request = 2; - } -} - -message WatchCreateRequest { - DnsPacket query = 1; -} - -message WatchCancelRequest { - // watch_id is the watcher id to cancel - int64 watch_id = 1; -} - -message WatchResponse { - // watch_id is the ID of the watcher that corresponds to the response. - int64 watch_id = 1; - - // created is set to true if the response is for a create watch request. - // The client should record the watch_id and expect to receive DNS replies - // from the same stream. - // All replies sent to the created watcher will attach with the same watch_id. - bool created = 2; - - // canceled is set to true if the response is for a cancel watch request. - // No further events will be sent to the canceled watcher. - bool canceled = 3; - - string qname = 4; - - string err = 5; } diff --git a/vendor/github.com/coredns/coredns/plugin/backend.go b/vendor/github.com/coredns/coredns/plugin/backend.go index b2d4df19e..32443a955 100644 --- a/vendor/github.com/coredns/coredns/plugin/backend.go +++ b/vendor/github.com/coredns/coredns/plugin/backend.go @@ -13,18 +13,18 @@ import ( type ServiceBackend interface { // Services communicates with the backend to retrieve the service definitions. Exact indicates // on exact match should be returned. - Services(state request.Request, exact bool, opt Options) ([]msg.Service, error) + Services(ctx context.Context, state request.Request, exact bool, opt Options) ([]msg.Service, error) // Reverse communicates with the backend to retrieve service definition based on a IP address // instead of a name. I.e. a reverse DNS lookup. - Reverse(state request.Request, exact bool, opt Options) ([]msg.Service, error) + Reverse(ctx context.Context, state request.Request, exact bool, opt Options) ([]msg.Service, error) // Lookup is used to find records else where. - Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error) + Lookup(ctx context.Context, state request.Request, name string, typ uint16) (*dns.Msg, error) // Returns _all_ services that matches a certain name. // Note: it does not implement a specific service. - Records(state request.Request, exact bool) ([]msg.Service, error) + Records(ctx context.Context, state request.Request, exact bool) ([]msg.Service, error) // IsNameError return true if err indicated a record not found condition IsNameError(err error) bool diff --git a/vendor/github.com/coredns/coredns/plugin/backend_lookup.go b/vendor/github.com/coredns/coredns/plugin/backend_lookup.go index 77e08174f..096cf806b 100644 --- a/vendor/github.com/coredns/coredns/plugin/backend_lookup.go +++ b/vendor/github.com/coredns/coredns/plugin/backend_lookup.go @@ -1,6 +1,7 @@ package plugin import ( + "context" "fmt" "math" "net" @@ -13,13 +14,13 @@ import ( ) // A returns A records from Backend or an error. -func A(b ServiceBackend, zone string, state request.Request, previousRecords []dns.RR, opt Options) (records []dns.RR, err error) { - services, err := checkForApex(b, zone, state, opt) +func A(ctx context.Context, b ServiceBackend, zone string, state request.Request, previousRecords []dns.RR, opt Options) (records []dns.RR, err error) { + services, err := checkForApex(ctx, b, zone, state, opt) if err != nil { return nil, err } - dup := make(map[string]bool) + dup := make(map[string]struct{}) for _, serv := range services { @@ -43,7 +44,7 @@ func A(b ServiceBackend, zone string, state request.Request, previousRecords []d if dns.IsSubDomain(zone, dns.Fqdn(serv.Host)) { state1 := state.NewWithQuestion(serv.Host, state.QType()) state1.Zone = zone - nextRecords, err := A(b, zone, state1, append(previousRecords, newRecord), opt) + nextRecords, err := A(ctx, b, zone, state1, append(previousRecords, newRecord), opt) if err == nil { // Not only have we found something we should add the CNAME and the IP addresses. @@ -57,7 +58,7 @@ func A(b ServiceBackend, zone string, state request.Request, previousRecords []d // This means we can not complete the CNAME, try to look else where. target := newRecord.Target // Lookup - m1, e1 := b.Lookup(state, target, state.QType()) + m1, e1 := b.Lookup(ctx, state, target, state.QType()) if e1 != nil { continue } @@ -68,7 +69,7 @@ func A(b ServiceBackend, zone string, state request.Request, previousRecords []d case dns.TypeA: if _, ok := dup[serv.Host]; !ok { - dup[serv.Host] = true + dup[serv.Host] = struct{}{} records = append(records, serv.NewA(state.QName(), ip)) } @@ -80,13 +81,13 @@ func A(b ServiceBackend, zone string, state request.Request, previousRecords []d } // AAAA returns AAAA records from Backend or an error. -func AAAA(b ServiceBackend, zone string, state request.Request, previousRecords []dns.RR, opt Options) (records []dns.RR, err error) { - services, err := checkForApex(b, zone, state, opt) +func AAAA(ctx context.Context, b ServiceBackend, zone string, state request.Request, previousRecords []dns.RR, opt Options) (records []dns.RR, err error) { + services, err := checkForApex(ctx, b, zone, state, opt) if err != nil { return nil, err } - dup := make(map[string]bool) + dup := make(map[string]struct{}) for _, serv := range services { @@ -111,7 +112,7 @@ func AAAA(b ServiceBackend, zone string, state request.Request, previousRecords if dns.IsSubDomain(zone, dns.Fqdn(serv.Host)) { state1 := state.NewWithQuestion(serv.Host, state.QType()) state1.Zone = zone - nextRecords, err := AAAA(b, zone, state1, append(previousRecords, newRecord), opt) + nextRecords, err := AAAA(ctx, b, zone, state1, append(previousRecords, newRecord), opt) if err == nil { // Not only have we found something we should add the CNAME and the IP addresses. @@ -124,7 +125,7 @@ func AAAA(b ServiceBackend, zone string, state request.Request, previousRecords } // This means we can not complete the CNAME, try to look else where. target := newRecord.Target - m1, e1 := b.Lookup(state, target, state.QType()) + m1, e1 := b.Lookup(ctx, state, target, state.QType()) if e1 != nil { continue } @@ -139,7 +140,7 @@ func AAAA(b ServiceBackend, zone string, state request.Request, previousRecords case dns.TypeAAAA: if _, ok := dup[serv.Host]; !ok { - dup[serv.Host] = true + dup[serv.Host] = struct{}{} records = append(records, serv.NewAAAA(state.QName(), ip)) } } @@ -149,14 +150,14 @@ func AAAA(b ServiceBackend, zone string, state request.Request, previousRecords // SRV returns SRV records from the Backend. // If the Target is not a name but an IP address, a name is created on the fly. -func SRV(b ServiceBackend, zone string, state request.Request, opt Options) (records, extra []dns.RR, err error) { - services, err := b.Services(state, false, opt) +func SRV(ctx context.Context, b ServiceBackend, zone string, state request.Request, opt Options) (records, extra []dns.RR, err error) { + services, err := b.Services(ctx, state, false, opt) if err != nil { return nil, nil, err } - dup := make(map[item]bool) - lookup := make(map[string]bool) + dup := make(map[item]struct{}) + lookup := make(map[string]struct{}) // Looping twice to get the right weight vs priority. This might break because we may drop duplicate SRV records latter on. w := make(map[int]int) @@ -196,15 +197,15 @@ func SRV(b ServiceBackend, zone string, state request.Request, opt Options) (rec break } - lookup[srv.Target] = true + lookup[srv.Target] = struct{}{} if !dns.IsSubDomain(zone, srv.Target) { - m1, e1 := b.Lookup(state, srv.Target, dns.TypeA) + m1, e1 := b.Lookup(ctx, state, srv.Target, dns.TypeA) if e1 == nil { extra = append(extra, m1.Answer...) } - m1, e1 = b.Lookup(state, srv.Target, dns.TypeAAAA) + m1, e1 = b.Lookup(ctx, state, srv.Target, dns.TypeAAAA) if e1 == nil { // If we have seen CNAME's we *assume* that they are already added. for _, a := range m1.Answer { @@ -218,7 +219,7 @@ func SRV(b ServiceBackend, zone string, state request.Request, opt Options) (rec // Internal name, we should have some info on them, either v4 or v6 // Clients expect a complete answer, because we are a recursor in their view. state1 := state.NewWithQuestion(srv.Target, dns.TypeA) - addr, e1 := A(b, zone, state1, nil, opt) + addr, e1 := A(ctx, b, zone, state1, nil, opt) if e1 == nil { extra = append(extra, addr...) } @@ -242,14 +243,14 @@ func SRV(b ServiceBackend, zone string, state request.Request, opt Options) (rec } // MX returns MX records from the Backend. If the Target is not a name but an IP address, a name is created on the fly. -func MX(b ServiceBackend, zone string, state request.Request, opt Options) (records, extra []dns.RR, err error) { - services, err := b.Services(state, false, opt) +func MX(ctx context.Context, b ServiceBackend, zone string, state request.Request, opt Options) (records, extra []dns.RR, err error) { + services, err := b.Services(ctx, state, false, opt) if err != nil { return nil, nil, err } - dup := make(map[item]bool) - lookup := make(map[string]bool) + dup := make(map[item]struct{}) + lookup := make(map[string]struct{}) for _, serv := range services { if !serv.Mail { continue @@ -263,15 +264,15 @@ func MX(b ServiceBackend, zone string, state request.Request, opt Options) (reco break } - lookup[mx.Mx] = true + lookup[mx.Mx] = struct{}{} if !dns.IsSubDomain(zone, mx.Mx) { - m1, e1 := b.Lookup(state, mx.Mx, dns.TypeA) + m1, e1 := b.Lookup(ctx, state, mx.Mx, dns.TypeA) if e1 == nil { extra = append(extra, m1.Answer...) } - m1, e1 = b.Lookup(state, mx.Mx, dns.TypeAAAA) + m1, e1 = b.Lookup(ctx, state, mx.Mx, dns.TypeAAAA) if e1 == nil { // If we have seen CNAME's we *assume* that they are already added. for _, a := range m1.Answer { @@ -284,7 +285,7 @@ func MX(b ServiceBackend, zone string, state request.Request, opt Options) (reco } // Internal name state1 := state.NewWithQuestion(mx.Mx, dns.TypeA) - addr, e1 := A(b, zone, state1, nil, opt) + addr, e1 := A(ctx, b, zone, state1, nil, opt) if e1 == nil { extra = append(extra, addr...) } @@ -308,8 +309,8 @@ func MX(b ServiceBackend, zone string, state request.Request, opt Options) (reco } // CNAME returns CNAME records from the backend or an error. -func CNAME(b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, err error) { - services, err := b.Services(state, true, opt) +func CNAME(ctx context.Context, b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, err error) { + services, err := b.Services(ctx, state, true, opt) if err != nil { return nil, err } @@ -324,34 +325,31 @@ func CNAME(b ServiceBackend, zone string, state request.Request, opt Options) (r } // TXT returns TXT records from Backend or an error. -func TXT(b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, err error) { - services, err := b.Services(state, false, opt) +func TXT(ctx context.Context, b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, err error) { + services, err := b.Services(ctx, state, false, opt) if err != nil { return nil, err } for _, serv := range services { - if serv.Text == "" { - continue - } records = append(records, serv.NewTXT(state.QName())) } return records, nil } // PTR returns the PTR records from the backend, only services that have a domain name as host are included. -func PTR(b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, err error) { - services, err := b.Reverse(state, true, opt) +func PTR(ctx context.Context, b ServiceBackend, zone string, state request.Request, opt Options) (records []dns.RR, err error) { + services, err := b.Reverse(ctx, state, true, opt) if err != nil { return nil, err } - dup := make(map[string]bool) + dup := make(map[string]struct{}) for _, serv := range services { if ip := net.ParseIP(serv.Host); ip == nil { if _, ok := dup[serv.Host]; !ok { - dup[serv.Host] = true + dup[serv.Host] = struct{}{} records = append(records, serv.NewPTR(state.QName(), serv.Host)) } } @@ -360,14 +358,14 @@ func PTR(b ServiceBackend, zone string, state request.Request, opt Options) (rec } // NS returns NS records from the backend -func NS(b ServiceBackend, zone string, state request.Request, opt Options) (records, extra []dns.RR, err error) { +func NS(ctx context.Context, b ServiceBackend, zone string, state request.Request, opt Options) (records, extra []dns.RR, err error) { // NS record for this zone live in a special place, ns.dns.. Fake our lookup. // only a tad bit fishy... old := state.QName() state.Clear() state.Req.Question[0].Name = "ns.dns." + zone - services, err := b.Services(state, false, opt) + services, err := b.Services(ctx, state, false, opt) if err != nil { return nil, nil, err } @@ -390,8 +388,14 @@ func NS(b ServiceBackend, zone string, state request.Request, opt Options) (reco } // SOA returns a SOA record from the backend. -func SOA(b ServiceBackend, zone string, state request.Request, opt Options) ([]dns.RR, error) { - header := dns.RR_Header{Name: zone, Rrtype: dns.TypeSOA, Ttl: 300, Class: dns.ClassINET} +func SOA(ctx context.Context, b ServiceBackend, zone string, state request.Request, opt Options) ([]dns.RR, error) { + minTTL := b.MinTTL(state) + ttl := uint32(300) + if minTTL < ttl { + ttl = minTTL + } + + header := dns.RR_Header{Name: zone, Rrtype: dns.TypeSOA, Ttl: ttl, Class: dns.ClassINET} Mbox := hostmaster + "." Ns := "ns.dns." @@ -407,19 +411,18 @@ func SOA(b ServiceBackend, zone string, state request.Request, opt Options) ([]d Refresh: 7200, Retry: 1800, Expire: 86400, - Minttl: b.MinTTL(state), + Minttl: minTTL, } return []dns.RR{soa}, nil } // BackendError writes an error response to the client. -func BackendError(b ServiceBackend, zone string, rcode int, state request.Request, err error, opt Options) (int, error) { +func BackendError(ctx context.Context, b ServiceBackend, zone string, rcode int, state request.Request, err error, opt Options) (int, error) { m := new(dns.Msg) m.SetRcode(state.Req, rcode) - m.Authoritative, m.RecursionAvailable = true, true - m.Ns, _ = SOA(b, zone, state, opt) + m.Authoritative = true + m.Ns, _ = SOA(ctx, b, zone, state, opt) - state.SizeAndDo(m) state.W.WriteMsg(m) // Return success as the rcode to signal we have written to the client. return dns.RcodeSuccess, err @@ -436,10 +439,10 @@ func newAddress(s msg.Service, name string, ip net.IP, what uint16) dns.RR { return &dns.AAAA{Hdr: hdr, AAAA: ip} } -// checkForApex checks the spcecial apex.dns directory for records that will be returned as A or AAAA. -func checkForApex(b ServiceBackend, zone string, state request.Request, opt Options) ([]msg.Service, error) { +// checkForApex checks the special apex.dns directory for records that will be returned as A or AAAA. +func checkForApex(ctx context.Context, b ServiceBackend, zone string, state request.Request, opt Options) ([]msg.Service, error) { if state.Name() != zone { - return b.Services(state, false, opt) + return b.Services(ctx, state, false, opt) } // If the zone name itself is queried we fake the query to search for a special entry @@ -448,14 +451,14 @@ func checkForApex(b ServiceBackend, zone string, state request.Request, opt Opti state.Clear() state.Req.Question[0].Name = dnsutil.Join("apex.dns", zone) - services, err := b.Services(state, false, opt) + services, err := b.Services(ctx, state, false, opt) if err == nil { state.Req.Question[0].Name = old return services, err } state.Req.Question[0].Name = old - return b.Services(state, false, opt) + return b.Services(ctx, state, false, opt) } // item holds records. @@ -467,17 +470,17 @@ type item struct { // isDuplicate uses m to see if the combo (name, addr, port) already exists. If it does // not exist already IsDuplicate will also add the record to the map. -func isDuplicate(m map[item]bool, name, addr string, port uint16) bool { +func isDuplicate(m map[item]struct{}, name, addr string, port uint16) bool { if addr != "" { _, ok := m[item{name, 0, addr}] if !ok { - m[item{name, 0, addr}] = true + m[item{name, 0, addr}] = struct{}{} } return ok } _, ok := m[item{name, port, ""}] if !ok { - m[item{name, port, ""}] = true + m[item{name, port, ""}] = struct{}{} } return ok } diff --git a/vendor/github.com/coredns/coredns/plugin/cache/README.md b/vendor/github.com/coredns/coredns/plugin/cache/README.md index ad2483ae9..8b2bdf075 100644 --- a/vendor/github.com/coredns/coredns/plugin/cache/README.md +++ b/vendor/github.com/coredns/coredns/plugin/cache/README.md @@ -19,7 +19,7 @@ cache [TTL] [ZONES...] ~~~ * **TTL** max TTL in seconds. If not specified, the maximum TTL will be used, which is 3600 for - noerror responses and 1800 for denial of existence ones. + NOERROR responses and 1800 for denial of existence ones. Setting a TTL of 300: `cache 300` would cache records up to 300 seconds. * **ZONES** zones it should cache for. If empty, the zones from the configuration block are used. @@ -88,13 +88,14 @@ Proxy to Google Public DNS and only cache responses for example.org (or below). ~~~ corefile . { - proxy . 8.8.8.8:53 + forward . 8.8.8.8:53 cache example.org } ~~~ Enable caching for all zones, keep a positive cache size of 5000 and a negative cache size of 2500: - ~~~ corefile + +~~~ corefile . { cache { success 5000 diff --git a/vendor/github.com/coredns/coredns/plugin/cache/cache.go b/vendor/github.com/coredns/coredns/plugin/cache/cache.go index cd0fda505..bc82bb604 100644 --- a/vendor/github.com/coredns/coredns/plugin/cache/cache.go +++ b/vendor/github.com/coredns/coredns/plugin/cache/cache.go @@ -118,7 +118,7 @@ type ResponseWriter struct { // newPrefetchResponseWriter returns a Cache ResponseWriter to be used in // prefetch requests. It ensures RemoteAddr() can be called even after the -// original connetion has already been closed. +// original connection has already been closed. func newPrefetchResponseWriter(server string, state request.Request, c *Cache) *ResponseWriter { // Resolve the address now, the connection might be already closed when the // actual prefetch request is made. diff --git a/vendor/github.com/coredns/coredns/plugin/done.go b/vendor/github.com/coredns/coredns/plugin/done.go new file mode 100644 index 000000000..3f53273da --- /dev/null +++ b/vendor/github.com/coredns/coredns/plugin/done.go @@ -0,0 +1,14 @@ +package plugin + +import "context" + +// Done is a non-blocking function that returns true if the context has been canceled. +func Done(ctx context.Context) bool { + select { + case <-ctx.Done(): + return true + default: + return false + } + return false +} diff --git a/vendor/github.com/coredns/coredns/plugin/errors/README.md b/vendor/github.com/coredns/coredns/plugin/errors/README.md index 70ec3a2c3..8b1449ea3 100644 --- a/vendor/github.com/coredns/coredns/plugin/errors/README.md +++ b/vendor/github.com/coredns/coredns/plugin/errors/README.md @@ -34,7 +34,7 @@ Option `consolidate` allows collecting several error messages matching the regul Multiple `consolidate` options with different **DURATION** and **REGEXP** are allowed. In case if some error message corresponds to several defined regular expressions the message will be associated with the first appropriate **REGEXP**. -For better performance, it's recomended to use the `^` or `$` metacharacters in regular expression when filtering error messages by prefix or suffix, e.g. `^failed to .*`, or `.* timeout$`. +For better performance, it's recommended to use the `^` or `$` metacharacters in regular expression when filtering error messages by prefix or suffix, e.g. `^failed to .*`, or `.* timeout$`. ## Examples diff --git a/vendor/github.com/coredns/coredns/plugin/errors/errors.go b/vendor/github.com/coredns/coredns/plugin/errors/errors.go index aa4b384b8..9565f11ab 100644 --- a/vendor/github.com/coredns/coredns/plugin/errors/errors.go +++ b/vendor/github.com/coredns/coredns/plugin/errors/errors.go @@ -35,28 +35,19 @@ func (p *pattern) setTimer(t *time.Timer) { // errorHandler handles DNS errors (and errors from other plugin). type errorHandler struct { patterns []*pattern - eLogger func(int, string, string, string) - cLogger func(uint32, string, time.Duration) stopFlag uint32 Next plugin.Handler } func newErrorHandler() *errorHandler { - return &errorHandler{eLogger: errorLogger, cLogger: consLogger} -} - -func errorLogger(code int, qName, qType, err string) { - log.Errorf("%d %s %s: %s", code, qName, qType, err) -} - -func consLogger(cnt uint32, pattern string, p time.Duration) { - log.Errorf("%d errors like '%s' occured in last %s", cnt, pattern, p) + return &errorHandler{} } func (h *errorHandler) logPattern(i int) { cnt := atomic.SwapUint32(&h.patterns[i].count, 0) if cnt > 0 { - h.cLogger(cnt, h.patterns[i].pattern.String(), h.patterns[i].period) + log.Errorf("%d errors like '%s' occurred in last %s", + cnt, h.patterns[i].pattern.String(), h.patterns[i].period) } } @@ -102,7 +93,7 @@ func (h *errorHandler) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dn } } state := request.Request{W: w, Req: r} - h.eLogger(rcode, state.Name(), state.Type(), strErr) + log.Errorf("%d %s %s: %s", rcode, state.Name(), state.Type(), strErr) } return rcode, err diff --git a/vendor/github.com/coredns/coredns/plugin/etcd/msg/path.go b/vendor/github.com/coredns/coredns/plugin/etcd/msg/path.go index dc7494782..c90798035 100644 --- a/vendor/github.com/coredns/coredns/plugin/etcd/msg/path.go +++ b/vendor/github.com/coredns/coredns/plugin/etcd/msg/path.go @@ -30,7 +30,7 @@ func Domain(s string) string { } // PathWithWildcard ascts as Path, but if a name contains wildcards (* or any), the name will be -// chopped of before the (first) wildcard, and we do a highler evel search and +// chopped of before the (first) wildcard, and we do a higher level search and // later find the matching names. So service.*.skydns.local, will look for all // services under skydns.local and will later check for names that match // service.*.skydns.local. If a wildcard is found the returned bool is true. diff --git a/vendor/github.com/coredns/coredns/plugin/etcd/msg/service.go b/vendor/github.com/coredns/coredns/plugin/etcd/msg/service.go index 987fb14c7..4e049e10a 100644 --- a/vendor/github.com/coredns/coredns/plugin/etcd/msg/service.go +++ b/vendor/github.com/coredns/coredns/plugin/etcd/msg/service.go @@ -38,15 +38,21 @@ type Service struct { // NewSRV returns a new SRV record based on the Service. func (s *Service) NewSRV(name string, weight uint16) *dns.SRV { - host := targetStrip(dns.Fqdn(s.Host), s.TargetStrip) + host := dns.Fqdn(s.Host) + if s.TargetStrip > 0 { + host = targetStrip(host, s.TargetStrip) + } return &dns.SRV{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeSRV, Class: dns.ClassINET, Ttl: s.TTL}, - Priority: uint16(s.Priority), Weight: weight, Port: uint16(s.Port), Target: dns.Fqdn(host)} + Priority: uint16(s.Priority), Weight: weight, Port: uint16(s.Port), Target: host} } // NewMX returns a new MX record based on the Service. func (s *Service) NewMX(name string) *dns.MX { - host := targetStrip(dns.Fqdn(s.Host), s.TargetStrip) + host := dns.Fqdn(s.Host) + if s.TargetStrip > 0 { + host = targetStrip(host, s.TargetStrip) + } return &dns.MX{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeMX, Class: dns.ClassINET, Ttl: s.TTL}, Preference: uint16(s.Priority), Mx: host} @@ -79,7 +85,10 @@ func (s *Service) NewPTR(name string, target string) *dns.PTR { // NewNS returns a new NS record based on the Service. func (s *Service) NewNS(name string) *dns.NS { - host := targetStrip(dns.Fqdn(s.Host), s.TargetStrip) + host := dns.Fqdn(s.Host) + if s.TargetStrip > 0 { + host = targetStrip(host, s.TargetStrip) + } return &dns.NS{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeNS, Class: dns.ClassINET, Ttl: s.TTL}, Ns: host} } @@ -155,10 +164,6 @@ func split255(s string) []string { // targetStrip strips "targetstrip" labels from the left side of the fully qualified name. func targetStrip(name string, targetStrip int) string { - if targetStrip == 0 { - return name - } - offset, end := 0, false for i := 0; i < targetStrip; i++ { offset, end = dns.NextLabel(name, offset) diff --git a/vendor/github.com/coredns/coredns/plugin/forward/README.md b/vendor/github.com/coredns/coredns/plugin/forward/README.md index c0a426aab..94e306ea8 100644 --- a/vendor/github.com/coredns/coredns/plugin/forward/README.md +++ b/vendor/github.com/coredns/coredns/plugin/forward/README.md @@ -21,10 +21,6 @@ connect to a random upstream (which may or may not work). This plugin can only be used once per Server Block. -How does *forward* relate to *proxy*? This plugin is the "new" version of *proxy* and is faster -because it re-uses connections to the upstreams. It also does in-band health checks - using DNS -instead of HTTP. Since it is newer it has a little less (production) mileage on it. - ## Syntax In its most basic form, a simple forwarder uses this syntax: @@ -79,8 +75,13 @@ forward FROM TO... { The server certificate is verified using the specified CA file * `tls_servername` **NAME** allows you to set a server name in the TLS configuration; for instance 9.9.9.9 - needs this to be set to `dns.quad9.net`. + needs this to be set to `dns.quad9.net`. Multiple upstreams are still allowed in this scenario, + but they have to use the same `tls_servername`. E.g. mixing 9.9.9.9 (QuadDNS) with 1.1.1.1 + (Cloudflare) will not work. * `policy` specifies the policy to use for selecting upstream servers. The default is `random`. + * `random` is a policy that implements random upstream selection. + * `round_robin` is a policy that selects hosts based on round robin ordering. + * `sequential` is a policy that selects hosts based on sequential ordering. * `health_check`, use a different **DURATION** for health checking, the default duration is 0.5s. Also note the TLS config is "global" for the whole forwarding proxy if you need a different @@ -160,6 +161,18 @@ service with health checks. } ~~~ +Or with multiple upstreams from the same provider + +~~~ corefile +. { + forward . tls://1.1.1.1 tls://1.0.0.1 { + tls_servername cloudflare-dns.com + health_check 5s + } + cache 30 +} +~~~ + ## Bugs The TLS config is global for the whole forwarding proxy if you need a different `tls_servername` for diff --git a/vendor/github.com/coredns/coredns/plugin/forward/connect.go b/vendor/github.com/coredns/coredns/plugin/forward/connect.go index 64edb395e..8fde2224b 100644 --- a/vendor/github.com/coredns/coredns/plugin/forward/connect.go +++ b/vendor/github.com/coredns/coredns/plugin/forward/connect.go @@ -69,14 +69,6 @@ func (t *Transport) Dial(proto string) (*dns.Conn, bool, error) { return conn, false, err } -func (p *Proxy) readTimeout() time.Duration { - return limitTimeout(&p.avgRtt, minTimeout, maxTimeout) -} - -func (p *Proxy) updateRtt(newRtt time.Duration) { - averageTimeout(&p.avgRtt, newRtt, cumulativeAvgWeight) -} - // Connect selects an upstream, sends the request and waits for a response. func (p *Proxy) Connect(ctx context.Context, state request.Request, opts options) (*dns.Msg, error) { start := time.Now() @@ -103,7 +95,6 @@ func (p *Proxy) Connect(ctx context.Context, state request.Request, opts options } conn.SetWriteDeadline(time.Now().Add(maxTimeout)) - reqTime := time.Now() if err := conn.WriteMsg(state.Req); err != nil { conn.Close() // not giving it back if err == io.EOF && cached { @@ -112,19 +103,23 @@ func (p *Proxy) Connect(ctx context.Context, state request.Request, opts options return nil, err } - conn.SetReadDeadline(time.Now().Add(p.readTimeout())) - ret, err := conn.ReadMsg() - if err != nil { - p.updateRtt(maxTimeout) - conn.Close() // not giving it back - if err == io.EOF && cached { - return nil, ErrCachedClosed + var ret *dns.Msg + conn.SetReadDeadline(time.Now().Add(readTimeout)) + for { + ret, err = conn.ReadMsg() + if err != nil { + conn.Close() // not giving it back + if err == io.EOF && cached { + return nil, ErrCachedClosed + } + return ret, err + } + // drop out-of-order responses + if state.Req.Id == ret.Id { + break } - return ret, err } - p.updateRtt(time.Since(reqTime)) - p.transport.Yield(conn) rc, ok := dns.RcodeToString[ret.Rcode] diff --git a/vendor/github.com/coredns/coredns/plugin/forward/dnstap.go b/vendor/github.com/coredns/coredns/plugin/forward/dnstap.go new file mode 100644 index 000000000..7866aa39b --- /dev/null +++ b/vendor/github.com/coredns/coredns/plugin/forward/dnstap.go @@ -0,0 +1,61 @@ +package forward + +import ( + "context" + "time" + + "github.com/coredns/coredns/plugin/dnstap" + "github.com/coredns/coredns/plugin/dnstap/msg" + "github.com/coredns/coredns/request" + + tap "github.com/dnstap/golang-dnstap" + "github.com/miekg/dns" +) + +func toDnstap(ctx context.Context, host string, f *Forward, state request.Request, reply *dns.Msg, start time.Time) error { + tapper := dnstap.TapperFromContext(ctx) + if tapper == nil { + return nil + } + // Query + b := msg.New().Time(start).HostPort(host) + opts := f.opts + t := "" + switch { + case opts.forceTCP: // TCP flag has precedence over UDP flag + t = "tcp" + case opts.preferUDP: + t = "udp" + default: + t = state.Proto() + } + + if t == "tcp" { + b.SocketProto = tap.SocketProtocol_TCP + } else { + b.SocketProto = tap.SocketProtocol_UDP + } + + if tapper.Pack() { + b.Msg(state.Req) + } + m, err := b.ToOutsideQuery(tap.Message_FORWARDER_QUERY) + if err != nil { + return err + } + tapper.TapMessage(m) + + // Response + if reply != nil { + if tapper.Pack() { + b.Msg(reply) + } + m, err := b.Time(time.Now()).ToOutsideResponse(tap.Message_FORWARDER_RESPONSE) + if err != nil { + return err + } + tapper.TapMessage(m) + } + + return nil +} diff --git a/vendor/github.com/coredns/coredns/plugin/forward/forward.go b/vendor/github.com/coredns/coredns/plugin/forward/forward.go index dfa1aaca1..da2e175fe 100644 --- a/vendor/github.com/coredns/coredns/plugin/forward/forward.go +++ b/vendor/github.com/coredns/coredns/plugin/forward/forward.go @@ -74,7 +74,7 @@ func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg i := 0 list := f.List() deadline := time.Now().Add(defaultTimeout) - + start := time.Now() for time.Now().Before(deadline) { if i >= len(list) { // reached the end of list, reset to begin @@ -116,7 +116,7 @@ func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg continue } // Retry with TCP if truncated and prefer_udp configured. - if err == dns.ErrTruncated && !opts.forceTCP && f.opts.preferUDP { + if ret != nil && ret.Truncated && !opts.forceTCP && f.opts.preferUDP { opts.forceTCP = true continue } @@ -126,8 +126,8 @@ func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg if child != nil { child.Finish() } + taperr := toDnstap(ctx, proxy.addr, f, state, ret, start) - ret, err = truncated(state, ret, err) upstreamErr = err if err != nil { @@ -144,15 +144,16 @@ func (f *Forward) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg // Check if the reply is correct; if not return FormErr. if !state.Match(ret) { - debug.Hexdumpf(ret, "Wrong reply for id: %d, %s/%d", state.QName(), state.QType()) + debug.Hexdumpf(ret, "Wrong reply for id: %d, %s %d", ret.Id, state.QName(), state.QType()) - formerr := state.ErrorMessage(dns.RcodeFormatError) + formerr := new(dns.Msg) + formerr.SetRcode(state.Req, dns.RcodeFormatError) w.WriteMsg(formerr) - return 0, nil + return 0, taperr } w.WriteMsg(ret) - return 0, nil + return 0, taperr } if upstreamErr != nil { diff --git a/vendor/github.com/coredns/coredns/plugin/forward/lookup.go b/vendor/github.com/coredns/coredns/plugin/forward/lookup.go deleted file mode 100644 index f6c9a0745..000000000 --- a/vendor/github.com/coredns/coredns/plugin/forward/lookup.go +++ /dev/null @@ -1,89 +0,0 @@ -// Package forward implements a forwarding proxy. It caches an upstream net.Conn for some time, so if the same -// client returns the upstream's Conn will be precached. Depending on how you benchmark this looks to be -// 50% faster than just opening a new connection for every client. It works with UDP and TCP and uses -// inband healthchecking. -package forward - -import ( - "context" - - "github.com/coredns/coredns/plugin/pkg/transport" - "github.com/coredns/coredns/request" - - "github.com/miekg/dns" -) - -// Forward forward the request in state as-is. Unlike Lookup that adds EDNS0 suffix to the message. -// Forward may be called with a nil f, an error is returned in that case. -func (f *Forward) Forward(state request.Request) (*dns.Msg, error) { - if f == nil { - return nil, ErrNoForward - } - - fails := 0 - var upstreamErr error - for _, proxy := range f.List() { - if proxy.Down(f.maxfails) { - fails++ - if fails < len(f.proxies) { - continue - } - // All upstream proxies are dead, assume healtcheck is complete broken and randomly - // select an upstream to connect to. - proxy = f.List()[0] - } - - ret, err := proxy.Connect(context.Background(), state, f.opts) - - ret, err = truncated(state, ret, err) - upstreamErr = err - - if err != nil { - if fails < len(f.proxies) { - continue - } - break - } - - // Check if the reply is correct; if not return FormErr. - if !state.Match(ret) { - return state.ErrorMessage(dns.RcodeFormatError), nil - } - - return ret, err - } - - if upstreamErr != nil { - return nil, upstreamErr - } - - return nil, ErrNoHealthy -} - -// Lookup will use name and type to forge a new message and will send that upstream. It will -// set any EDNS0 options correctly so that downstream will be able to process the reply. -// Lookup may be called with a nil f, an error is returned in that case. -func (f *Forward) Lookup(state request.Request, name string, typ uint16) (*dns.Msg, error) { - if f == nil { - return nil, ErrNoForward - } - - req := new(dns.Msg) - req.SetQuestion(name, typ) - state.SizeAndDo(req) - - state2 := request.Request{W: state.W, Req: req} - - return f.Forward(state2) -} - -// NewLookup returns a Forward that can be used for plugin that need an upstream to resolve external names. -// Note that the caller must run Close on the forward to stop the health checking goroutines. -func NewLookup(addr []string) *Forward { - f := New() - for i := range addr { - p := NewProxy(addr[i], transport.DNS) - f.SetProxy(p) - } - return f -} diff --git a/vendor/github.com/coredns/coredns/plugin/forward/persistent.go b/vendor/github.com/coredns/coredns/plugin/forward/persistent.go index fabdc70b2..d1348f94d 100644 --- a/vendor/github.com/coredns/coredns/plugin/forward/persistent.go +++ b/vendor/github.com/coredns/coredns/plugin/forward/persistent.go @@ -31,7 +31,7 @@ type Transport struct { func newTransport(addr string) *Transport { t := &Transport{ - avgDialTime: int64(defaultDialTimeout / 2), + avgDialTime: int64(maxDialTimeout / 2), conns: make(map[string][]*persistConn), expire: defaultExpire, addr: addr, @@ -159,8 +159,10 @@ func (t *Transport) SetExpire(expire time.Duration) { t.expire = expire } func (t *Transport) SetTLSConfig(cfg *tls.Config) { t.tlsConfig = cfg } const ( - defaultExpire = 10 * time.Second - minDialTimeout = 100 * time.Millisecond - maxDialTimeout = 30 * time.Second - defaultDialTimeout = 30 * time.Second + defaultExpire = 10 * time.Second + minDialTimeout = 1 * time.Second + maxDialTimeout = 30 * time.Second + + // Some resolves might take quite a while, usually (cached) responses are fast. Set to 2s to give us some time to retry a different upstream. + readTimeout = 2 * time.Second ) diff --git a/vendor/github.com/coredns/coredns/plugin/forward/proxy.go b/vendor/github.com/coredns/coredns/plugin/forward/proxy.go index fbe79cd69..bf4d68dca 100644 --- a/vendor/github.com/coredns/coredns/plugin/forward/proxy.go +++ b/vendor/github.com/coredns/coredns/plugin/forward/proxy.go @@ -11,8 +11,7 @@ import ( // Proxy defines an upstream host. type Proxy struct { - avgRtt int64 - fails uint32 + fails uint32 addr string @@ -32,7 +31,6 @@ func NewProxy(addr, trans string) *Proxy { fails: 0, probe: up.New(), transport: newTransport(addr), - avgRtt: int64(maxTimeout / 2), } p.health = NewHealthChecker(trans) runtime.SetFinalizer(p, (*Proxy).finalizer) diff --git a/vendor/github.com/coredns/coredns/plugin/forward/truncated.go b/vendor/github.com/coredns/coredns/plugin/forward/truncated.go deleted file mode 100644 index fb821d335..000000000 --- a/vendor/github.com/coredns/coredns/plugin/forward/truncated.go +++ /dev/null @@ -1,29 +0,0 @@ -package forward - -import ( - "github.com/coredns/coredns/request" - - "github.com/miekg/dns" -) - -// truncated looks at the error and if truncated return a nil error -// and a possible reconstructed dns message if that was nil. -func truncated(state request.Request, ret *dns.Msg, err error) (*dns.Msg, error) { - // If you query for instance ANY isc.org; you get a truncated query back which miekg/dns fails to unpack - // because the RRs are not finished. The returned message can be useful or useless. Return the original - // query with some header bits set that they should retry with TCP. - if err != dns.ErrTruncated { - return ret, err - } - - // We may or may not have something sensible... if not reassemble something to send to the client. - m := ret - if ret == nil { - m = new(dns.Msg) - m.SetReply(state.Req) - m.Truncated = true - m.Authoritative = true - m.Rcode = dns.RcodeSuccess - } - return m, nil -} diff --git a/vendor/github.com/coredns/coredns/plugin/health/README.md b/vendor/github.com/coredns/coredns/plugin/health/README.md index 1907a98c1..68afeac06 100644 --- a/vendor/github.com/coredns/coredns/plugin/health/README.md +++ b/vendor/github.com/coredns/coredns/plugin/health/README.md @@ -6,9 +6,8 @@ ## Description -By enabling *health* any plugin that implements -[healt.Healther interface](https://godoc.org/github.com/coredns/coredns/plugin/health#Healther) -will be queried for it's health. The combined health is exported, by default, on port 8080/health . +Enabled process wide health endpoint. When CoreDNS is up and running this returns a 200 OK http +status code. The health is exported, by default, on port 8080/health . ## Syntax @@ -17,12 +16,9 @@ health [ADDRESS] ~~~ Optionally takes an address; the default is `:8080`. The health path is fixed to `/health`. The -health endpoint returns a 200 response code and the word "OK" when this server is healthy. It returns -a 503. *health* periodically (1s) polls plugins that exports health information. If any of the -plugins signals that it is unhealthy, the server will go unhealthy too. Each plugin that supports -health checks has a section "Health" in their README. +health endpoint returns a 200 response code and the word "OK" when this server is healthy. -More options can be set with this extended syntax: +An extra option can be set with this extended syntax: ~~~ health [ADDRESS] { @@ -33,8 +29,8 @@ health [ADDRESS] { * Where `lameduck` will make the process unhealthy then *wait* for **DURATION** before the process shuts down. -If you have multiple Server Blocks and need to export health for each of the plugins, you must run -health endpoints on different ports: +If you have multiple Server Blocks, *health* should only be enabled in one of them (as it is process +wide). If you really need multiple endpoints, you must run health endpoints on different ports: ~~~ corefile com { @@ -48,21 +44,6 @@ net { } ~~~ -Note that if you format this in one server block you will get an error on startup, that the second -server can't setup the health plugin (on the same port). - -~~~ txt -com net { - whoami - erratic - health :8080 -} -~~~ - -## Plugins - -Any plugin that implements the Healther interface will be used to report health. - ## Metrics If monitoring is enabled (via the *prometheus* directive) then the following metric is exported: @@ -96,7 +77,7 @@ Set a lameduck duration of 1 second: ## Bugs -When reloading, the Health handler is stopped before the new server instance is started. -If that new server fails to start, then the initial server instance is still available and DNS queries still served, -but Health handler stays down. -Health will not reply HTTP request until a successful reload or a complete restart of CoreDNS. +When reloading, the health handler is stopped before the new server instance is started. If that +new server fails to start, then the initial server instance is still available and DNS queries still +served, but health handler stays down. Health will not reply HTTP request until a successful reload +or a complete restart of CoreDNS. diff --git a/vendor/github.com/coredns/coredns/plugin/health/health.go b/vendor/github.com/coredns/coredns/plugin/health/health.go index 7f35b0709..895704409 100644 --- a/vendor/github.com/coredns/coredns/plugin/health/health.go +++ b/vendor/github.com/coredns/coredns/plugin/health/health.go @@ -5,7 +5,6 @@ import ( "io" "net" "net/http" - "sync" "time" clog "github.com/coredns/coredns/plugin/pkg/log" @@ -22,18 +21,12 @@ type health struct { nlSetup bool mux *http.ServeMux - // A slice of Healthers that the health plugin will poll every second for their health status. - h []Healther - sync.RWMutex - ok bool // ok is the global boolean indicating an all healthy plugin stack - - stop chan bool - pollstop chan bool + stop chan bool } // newHealth returns a new initialized health. func newHealth(addr string) *health { - return &health{Addr: addr, stop: make(chan bool), pollstop: make(chan bool)} + return &health{Addr: addr, stop: make(chan bool)} } func (h *health) OnStartup() error { @@ -51,12 +44,10 @@ func (h *health) OnStartup() error { h.nlSetup = true h.mux.HandleFunc(path, func(w http.ResponseWriter, r *http.Request) { - if h.Ok() { - w.WriteHeader(http.StatusOK) - io.WriteString(w, ok) - return - } - w.WriteHeader(http.StatusServiceUnavailable) + // We're always healthy. + w.WriteHeader(http.StatusOK) + io.WriteString(w, ok) + return }) go func() { http.Serve(h.ln, h.mux) }() @@ -72,11 +63,6 @@ func (h *health) OnFinalShutdown() error { return nil } - // Stop polling plugins - h.pollstop <- true - // NACK health - h.SetOk(false) - if h.lameduck > 0 { log.Infof("Going into lameduck mode for %s", h.lameduck) time.Sleep(h.lameduck) @@ -84,8 +70,8 @@ func (h *health) OnFinalShutdown() error { h.ln.Close() - h.stop <- true h.nlSetup = false + close(h.stop) return nil } diff --git a/vendor/github.com/coredns/coredns/plugin/health/healther.go b/vendor/github.com/coredns/coredns/plugin/health/healther.go deleted file mode 100644 index 8bb6c907c..000000000 --- a/vendor/github.com/coredns/coredns/plugin/health/healther.go +++ /dev/null @@ -1,36 +0,0 @@ -package health - -// Healther interface needs to be implemented by each plugin willing to provide -// healthhceck information to the health plugin. Note this method should return -// quickly, i.e. just checking a boolean status, as it is called every second -// from the health plugin. -type Healther interface { - // Health returns a boolean indicating the health status of a plugin. - // False indicates unhealthy. - Health() bool -} - -// Ok returns the global health status of all plugin configured in this server. -func (h *health) Ok() bool { - h.RLock() - defer h.RUnlock() - return h.ok -} - -// SetOk sets the global health status of all plugin configured in this server. -func (h *health) SetOk(ok bool) { - h.Lock() - defer h.Unlock() - h.ok = ok -} - -// poll polls all healthers and sets the global state. -func (h *health) poll() { - for _, m := range h.h { - if !m.Health() { - h.SetOk(false) - return - } - } - h.SetOk(true) -} diff --git a/vendor/github.com/coredns/coredns/plugin/health/setup.go b/vendor/github.com/coredns/coredns/plugin/health/setup.go index 5a1725125..19aeba58d 100644 --- a/vendor/github.com/coredns/coredns/plugin/health/setup.go +++ b/vendor/github.com/coredns/coredns/plugin/health/setup.go @@ -5,7 +5,6 @@ import ( "net" "time" - "github.com/coredns/coredns/core/dnsserver" "github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin/metrics" @@ -28,32 +27,6 @@ func setup(c *caddy.Controller) error { h := newHealth(addr) h.lameduck = lame - c.OnStartup(func() error { - plugins := dnsserver.GetConfig(c).Handlers() - for _, p := range plugins { - if x, ok := p.(Healther); ok { - h.h = append(h.h, x) - } - } - return nil - }) - - c.OnStartup(func() error { - // Poll all middleware every second. - h.poll() - go func() { - for { - select { - case <-time.After(1 * time.Second): - h.poll() - case <-h.pollstop: - return - } - } - }() - return nil - }) - c.OnStartup(func() error { metrics.MustRegister(c, HealthDuration) return nil diff --git a/vendor/github.com/coredns/coredns/plugin/log/README.md b/vendor/github.com/coredns/coredns/plugin/log/README.md index 48e5acb6c..bbd853bd3 100644 --- a/vendor/github.com/coredns/coredns/plugin/log/README.md +++ b/vendor/github.com/coredns/coredns/plugin/log/README.md @@ -23,16 +23,18 @@ log Or if you want/need slightly more control: ~~~ txt -log [NAME] [FORMAT] +log [NAMES...] [FORMAT] ~~~ -* `NAME` is the name to match in order to be logged -* `FORMAT` is the log format to use (default is Common Log Format) +* `NAMES` is the name list to match in order to be logged +* `FORMAT` is the log format to use (default is Common Log Format), `{common}` is used as a shortcut + for the Common Log Format. You can also use `{combined}` for a format that adds the query opcode + `{>opcode}` to the Common Log Format. You can further specify the classes of responses that get logged: ~~~ txt -log [NAME] [FORMAT] { +log [NAMES...] [FORMAT] { class CLASSES... } ~~~ @@ -42,10 +44,12 @@ log [NAME] [FORMAT] { The classes of responses have the following meaning: * `success`: successful response -* `denial`: either NXDOMAIN or NODATA (name exists, type does not) +* `denial`: either NXDOMAIN or nodata responses (Name exists, type does not). A nodata response + sets the return code to NOERROR. * `error`: SERVFAIL, NOTIMP, REFUSED, etc. Anything that indicates the remote server is not willing to resolve the request. -* `all`: the default - nothing is specified. Using of this class means that all messages will be logged whatever we mix together with "all". +* `all`: the default - nothing is specified. Using of this class means that all messages will be + logged whatever we mix together with "all". If no class is specified, it defaults to *all*. @@ -61,6 +65,7 @@ The following place holders are supported: * `{class}`: qclass of the request * `{proto}`: protocol used (tcp or udp) * `{remote}`: client's IP address, for IPv6 addresses these are enclosed in brackets: `[::1]` +* `{local}`: server's IP address, for IPv6 addresses these are enclosed in brackets: `[::1]` * `{size}`: request size in bytes * `{port}`: client's port * `{duration}`: response duration @@ -72,6 +77,11 @@ The following place holders are supported: * `{>do}`: is the EDNS0 DO (DNSSEC OK) bit set in the query * `{>id}`: query ID * `{>opcode}`: query OPCODE +* `{common}`: the default Common Log Format. +* `{combined}`: the Common Log Format with the query opcode. +* `{/LABEL}`: any metadata label is accepted as a place holder if it is enclosed between `{/` and + `}`, the place holder will be replaced by the corresponding metadata value or the default value + `-` if label is not defined. See the *metadata* plugin for more information. The default Common Log Format is: @@ -104,7 +114,7 @@ Custom log format, for all zones (`.`) } ~~~ -Only log denials for example.org (and below to a file) +Only log denials (NXDOMAIN and nodata) for example.org (and below) ~~~ corefile . { @@ -114,11 +124,11 @@ Only log denials for example.org (and below to a file) } ~~~ -Log all queries which were not resolved successfully +Log all queries which were not resolved successfully in the Combined Log Format. ~~~ corefile . { - log . { + log . {combined} { class denial error } } diff --git a/vendor/github.com/coredns/coredns/plugin/log/log.go b/vendor/github.com/coredns/coredns/plugin/log/log.go index 685c55191..49581dfc4 100644 --- a/vendor/github.com/coredns/coredns/plugin/log/log.go +++ b/vendor/github.com/coredns/coredns/plugin/log/log.go @@ -6,10 +6,8 @@ import ( "time" "github.com/coredns/coredns/plugin" - "github.com/coredns/coredns/plugin/metrics/vars" "github.com/coredns/coredns/plugin/pkg/dnstest" clog "github.com/coredns/coredns/plugin/pkg/log" - "github.com/coredns/coredns/plugin/pkg/rcode" "github.com/coredns/coredns/plugin/pkg/replacer" "github.com/coredns/coredns/plugin/pkg/response" "github.com/coredns/coredns/request" @@ -19,9 +17,10 @@ import ( // Logger is a basic request logging plugin. type Logger struct { - Next plugin.Handler - Rules []Rule - ErrorFunc func(context.Context, dns.ResponseWriter, *dns.Msg, int) // failover error handler + Next plugin.Handler + Rules []Rule + + repl replacer.Replacer } // ServeDNS implements the plugin.Handler interface. @@ -35,30 +34,15 @@ func (l Logger) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) rrw := dnstest.NewRecorder(w) rc, err := plugin.NextOrFailure(l.Name(), l.Next, ctx, rrw, r) - if rc > 0 { - // There was an error up the chain, but no response has been written yet. - // The error must be handled here so the log entry will record the response size. - if l.ErrorFunc != nil { - l.ErrorFunc(ctx, rrw, r, rc) - } else { - answer := new(dns.Msg) - answer.SetRcode(r, rc) - state.SizeAndDo(answer) - - vars.Report(ctx, state, vars.Dropped, rcode.ToString(rc), answer.Len(), time.Now()) - - w.WriteMsg(answer) - } - rc = 0 - } - tpe, _ := response.Typify(rrw.Msg, time.Now().UTC()) class := response.Classify(tpe) // If we don't set up a class in config, the default "all" will be added // and we shouldn't have an empty rule.Class. - if rule.Class[response.All] || rule.Class[class] { - rep := replacer.New(r, rrw, CommonLogEmptyValue) - clog.Infof(rep.Replace(rule.Format)) + _, ok := rule.Class[response.All] + _, ok1 := rule.Class[class] + if ok || ok1 { + logstr := l.repl.Replace(ctx, state, rrw, rule.Format) + clog.Infof(logstr) } return rc, err @@ -73,15 +57,13 @@ func (l Logger) Name() string { return "log" } // Rule configures the logging plugin. type Rule struct { NameScope string - Class map[response.Class]bool + Class map[response.Class]struct{} Format string } const ( // CommonLogFormat is the common log format. - CommonLogFormat = `{remote}:{port} ` + CommonLogEmptyValue + ` {>id} "{type} {class} {name} {proto} {size} {>do} {>bufsize}" {rcode} {>rflags} {rsize} {duration}` - // CommonLogEmptyValue is the common empty log value. - CommonLogEmptyValue = "-" + CommonLogFormat = `{remote}:{port} ` + replacer.EmptyValue + ` {>id} "{type} {class} {name} {proto} {size} {>do} {>bufsize}" {rcode} {>rflags} {rsize} {duration}` // CombinedLogFormat is the combined log format. CombinedLogFormat = CommonLogFormat + ` "{>opcode}"` // DefaultLogFormat is the default log format. diff --git a/vendor/github.com/coredns/coredns/plugin/log/setup.go b/vendor/github.com/coredns/coredns/plugin/log/setup.go index c3c1af4ca..b9ecb1f72 100644 --- a/vendor/github.com/coredns/coredns/plugin/log/setup.go +++ b/vendor/github.com/coredns/coredns/plugin/log/setup.go @@ -1,8 +1,11 @@ package log import ( + "strings" + "github.com/coredns/coredns/core/dnsserver" "github.com/coredns/coredns/plugin" + "github.com/coredns/coredns/plugin/pkg/replacer" "github.com/coredns/coredns/plugin/pkg/response" "github.com/mholt/caddy" @@ -23,7 +26,7 @@ func setup(c *caddy.Controller) error { } dnsserver.GetConfig(c).AddPlugin(func(next plugin.Handler) plugin.Handler { - return Logger{Next: next, Rules: rules, ErrorFunc: dnsserver.DefaultErrorFunc} + return Logger{Next: next, Rules: rules, repl: replacer.New()} }) return nil @@ -34,62 +37,75 @@ func logParse(c *caddy.Controller) ([]Rule, error) { for c.Next() { args := c.RemainingArgs() + length := len(rules) - if len(args) == 0 { + switch len(args) { + case 0: // Nothing specified; use defaults rules = append(rules, Rule{ NameScope: ".", Format: DefaultLogFormat, - Class: make(map[response.Class]bool), + Class: make(map[response.Class]struct{}), }) - } else if len(args) == 1 { + case 1: rules = append(rules, Rule{ NameScope: dns.Fqdn(args[0]), Format: DefaultLogFormat, - Class: make(map[response.Class]bool), + Class: make(map[response.Class]struct{}), }) - } else { - // Name scope, and maybe a format specified + default: + // Name scopes, and maybe a format specified format := DefaultLogFormat - switch args[1] { - case "{common}": - format = CommonLogFormat - case "{combined}": - format = CombinedLogFormat - default: - format = args[1] + if strings.Contains(args[len(args)-1], "{") { + switch args[len(args)-1] { + case "{common}": + format = CommonLogFormat + case "{combined}": + format = CombinedLogFormat + default: + format = args[len(args)-1] + } + + args = args[:len(args)-1] } - rules = append(rules, Rule{ - NameScope: dns.Fqdn(args[0]), - Format: format, - Class: make(map[response.Class]bool), - }) + for _, str := range args { + rules = append(rules, Rule{ + NameScope: dns.Fqdn(str), + Format: format, + Class: make(map[response.Class]struct{}), + }) + } } // Class refinements in an extra block. + classes := make(map[response.Class]struct{}) for c.NextBlock() { switch c.Val() { // class followed by combinations of all, denial, error and success. case "class": - classes := c.RemainingArgs() - if len(classes) == 0 { + classesArgs := c.RemainingArgs() + if len(classesArgs) == 0 { return nil, c.ArgErr() } - for _, c := range classes { + for _, c := range classesArgs { cls, err := response.ClassFromString(c) if err != nil { return nil, err } - rules[len(rules)-1].Class[cls] = true + classes[cls] = struct{}{} } default: return nil, c.ArgErr() } } - if len(rules[len(rules)-1].Class) == 0 { - rules[len(rules)-1].Class[response.All] = true + if len(classes) == 0 { + classes[response.All] = struct{}{} + } + + for i := len(rules) - 1; i >= length; i -= 1 { + rules[i].Class = classes } } diff --git a/vendor/github.com/coredns/coredns/plugin/loop/README.md b/vendor/github.com/coredns/coredns/plugin/loop/README.md index 9bc51be49..c893ed050 100644 --- a/vendor/github.com/coredns/coredns/plugin/loop/README.md +++ b/vendor/github.com/coredns/coredns/plugin/loop/README.md @@ -7,10 +7,10 @@ ## Description The *loop* plugin will send a random probe query to ourselves and will then keep track of how many times -we see it. If we see it more than twice, we assume CoreDNS is looping and we halt the process. +we see it. If we see it more than twice, we assume CoreDNS has seen a forwarding loop and we halt the process. The plugin will try to send the query for up to 30 seconds. This is done to give CoreDNS enough time -to start up. Once a query has been successfully sent *loop* disables itself to prevent a query of +to start up. Once a query has been successfully sent, *loop* disables itself to prevent a query of death. The query sent is `..zone` with type set to HINFO. @@ -36,50 +36,56 @@ forwards to it self. After CoreDNS has started it stops the process while logging: ~~~ txt -plugin/loop: Forwarding loop detected in "." zone. Exiting. See https://coredns.io/plugins/loop#troubleshooting. Probe query: "HINFO 5577006791947779410.8674665223082153551.". +plugin/loop: Loop (127.0.0.1:55953 -> :1053) detected for zone ".", see https://coredns.io/plugins/loop#troubleshooting. Query: "HINFO 4547991504243258144.3688648895315093531." ~~~ ## Limitations -This plugin only attempts to find simple static forwarding loops at start up time. To detect a loop, all of the following must be true +This plugin only attempts to find simple static forwarding loops at start up time. To detect a loop, +the following must be true: -* the loop must be present at start up time. -* the loop must occur for at least the `HINFO` query type. +* the loop must be present at start up time. + +* the loop must occur for the `HINFO` query type. ## Troubleshooting -When CoreDNS logs contain the message `Forwarding loop detected ...`, this means that -the `loop` detection plugin has detected an infinite forwarding loop in one of the upstream -DNS servers. This is a fatal error because operating with an infinite loop will consume -memory and CPU until eventual out of memory death by the host. +When CoreDNS logs contain the message `Loop ... detected ...`, this means that the `loop` detection +plugin has detected an infinite forwarding loop in one of the upstream DNS servers. This is a fatal +error because operating with an infinite loop will consume memory and CPU until eventual out of +memory death by the host. A forwarding loop is usually caused by: * Most commonly, CoreDNS forwarding requests directly to itself. e.g. via a loopback address such as `127.0.0.1`, `::1` or `127.0.0.53` * Less commonly, CoreDNS forwarding to an upstream server that in turn, forwards requests back to CoreDNS. -To troubleshoot this problem, look in your Corefile for any `proxy` or `forward` to the zone +To troubleshoot this problem, look in your Corefile for any `forward`s to the zone in which the loop was detected. Make sure that they are not forwarding to a local address or -to another DNS server that is forwarding requests back to CoreDNS. If `proxy` or `forward` are - using a file (e.g. `/etc/resolv.conf`), make sure that file does not contain local addresses. +to another DNS server that is forwarding requests back to CoreDNS. If `forward` is +using a file (e.g. `/etc/resolv.conf`), make sure that file does not contain local addresses. ### Troubleshooting Loops In Kubernetes Clusters + When a CoreDNS Pod deployed in Kubernetes detects a loop, the CoreDNS Pod will start to "CrashLoopBackOff". This is because Kubernetes will try to restart the Pod every time CoreDNS detects the loop and exits. -A common cause of forwarding loops in Kubernetes clusters is an interaction with -`systemd-resolved` on the host node. `systemd-resolved` will, in certain configurations, -put `127.0.0.53` as an upstream into `/etc/resolv.conf`. Kubernetes (`kubelet`) by default -will pass this `/etc/resolv/conf` file to all Pods using the `default` dnsPolicy (this -includes CoreDNS Pods). CoreDNS then uses this `/etc/resolv.conf` as a list of upstreams -to proxy/forward requests to. Since it contains a local address, CoreDNS ends up forwarding +A common cause of forwarding loops in Kubernetes clusters is an interaction with a local DNS cache +on the host node (e.g. `systemd-resolved`). For example, in certain configurations `systemd-resolved` will +put the loopback address `127.0.0.53` as a nameserver into `/etc/resolv.conf`. Kubernetes (via `kubelet`) by default +will pass this `/etc/resolv.conf` file to all Pods using the `default` dnsPolicy rendering them +unable to make DNS lookups (this includes CoreDNS Pods). CoreDNS uses this `/etc/resolv.conf` +as a list of upstreams to forward requests to. Since it contains a loopback address, CoreDNS ends up forwarding requests to itself. There are many ways to work around this issue, some are listed here: -* Add the following to `kubelet`: `--resolv-conf /run/systemd/resolve/resolv.conf`. This flag -tells `kubelet` to pass an alternate `resolv.conf` to Pods. For `systemd-resolved`, -`/run/systemd/resolve/resolv.conf` is typically the location of the "original" `/etc/resolv.conf`. -* Disable `systemd-resolved` on host nodes, and restore `/etc/resolv.conf` to the original. -* A quick and dirty fix is to edit your Corefile, replacing `proxy . /etc/resolv.conf` with -the ip address of your upstream DNS, for example `proxy . 8.8.8.8`. +* Add the following to `kubelet`: `--resolv-conf `. Your "real" + `resolv.conf` is the one that contains the actual IPs of your upstream servers, and no local/loopback address. + This flag tells `kubelet` to pass an alternate `resolv.conf` to Pods. For systems using `systemd-resolved`, +`/run/systemd/resolve/resolv.conf` is typically the location of the "real" `resolv.conf`, +although this can be different depending on your distribution. +* Disable the local DNS cache on host nodes, and restore `/etc/resolv.conf` to the original. +* A quick and dirty fix is to edit your Corefile, replacing `forward . /etc/resolv.conf` with +the ip address of your upstream DNS, for example `forward . 8.8.8.8`. But this only fixes the issue for CoreDNS, +kubelet will continue to forward the invalid `resolv.conf` to all `default` dnsPolicy Pods, leaving them unable to resolve DNS. diff --git a/vendor/github.com/coredns/coredns/plugin/loop/loop.go b/vendor/github.com/coredns/coredns/plugin/loop/loop.go index 45bdc4267..8d29798ad 100644 --- a/vendor/github.com/coredns/coredns/plugin/loop/loop.go +++ b/vendor/github.com/coredns/coredns/plugin/loop/loop.go @@ -19,6 +19,7 @@ type Loop struct { zone string qname string + addr string sync.RWMutex i int @@ -49,7 +50,7 @@ func (l *Loop) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) ( } if l.seen() > 2 { - log.Fatalf("Forwarding loop detected in \"%s\" zone. Exiting. See https://coredns.io/plugins/loop#troubleshooting. Probe query: \"HINFO %s\".", l.zone, l.qname) + log.Fatalf(`Loop (%s -> %s) detected for zone %q, see https://coredns.io/plugins/loop#troubleshooting. Query: "HINFO %s"`, state.RemoteAddr(), l.address(), l.zone, l.qname) } return plugin.NextOrFailure(l.Name(), l.Next, ctx, w, r) @@ -94,3 +95,15 @@ func (l *Loop) disabled() bool { defer l.RUnlock() return l.off } + +func (l *Loop) setAddress(addr string) { + l.Lock() + defer l.Unlock() + l.addr = addr +} + +func (l *Loop) address() string { + l.RLock() + defer l.RUnlock() + return l.addr +} diff --git a/vendor/github.com/coredns/coredns/plugin/loop/setup.go b/vendor/github.com/coredns/coredns/plugin/loop/setup.go index ba4681cb4..db6821341 100644 --- a/vendor/github.com/coredns/coredns/plugin/loop/setup.go +++ b/vendor/github.com/coredns/coredns/plugin/loop/setup.go @@ -41,6 +41,7 @@ func setup(c *caddy.Controller) error { addr := net.JoinHostPort(lh, conf.Port) for time.Now().Before(deadline) { + l.setAddress(addr) if _, err := l.exchange(addr); err != nil { l.reset() time.Sleep(1 * time.Second) diff --git a/vendor/github.com/coredns/coredns/plugin/metrics/README.md b/vendor/github.com/coredns/coredns/plugin/metrics/README.md index b3fbc111f..5aec4e97b 100644 --- a/vendor/github.com/coredns/coredns/plugin/metrics/README.md +++ b/vendor/github.com/coredns/coredns/plugin/metrics/README.md @@ -19,6 +19,7 @@ The following metrics are exported: * `coredns_dns_request_type_count_total{server, zone, type}` - counter of queries per zone and type. * `coredns_dns_response_size_bytes{server, zone, proto}` - response size in bytes. * `coredns_dns_response_rcode_count_total{server, zone, rcode}` - response per zone and rcode. +* `coredns_plugin_enabled{server, zone, name}` - indicates whether a plugin is enabled on per server and zone basis. Each counter has a label `zone` which is the zonename used for the request/response. @@ -47,12 +48,12 @@ prometheus [ADDRESS] For each zone that you want to see metrics for. -It optionally takes an address to which the metrics are exported; the default -is `localhost:9153`. The metrics path is fixed to `/metrics`. +It optionally takes a bind address to which the metrics are exported; the default +listens on `localhost:9153`. The metrics path is fixed to `/metrics`. ## Examples -Use an alternative address: +Use an alternative listening address: ~~~ corefile . { @@ -75,3 +76,4 @@ When reloading, the Prometheus handler is stopped before the new server instance If that new server fails to start, then the initial server instance is still available and DNS queries still served, but Prometheus handler stays down. Prometheus will not reply HTTP request until a successful reload or a complete restart of CoreDNS. +Only the plugins that register as Handler are visible in `coredns_plugin_enabled{server, zone, name}`. As of today the plugins reload and bind will not be reported. diff --git a/vendor/github.com/coredns/coredns/plugin/metrics/context.go b/vendor/github.com/coredns/coredns/plugin/metrics/context.go index 7ee25ef4a..da6bdb12d 100644 --- a/vendor/github.com/coredns/coredns/plugin/metrics/context.go +++ b/vendor/github.com/coredns/coredns/plugin/metrics/context.go @@ -3,7 +3,7 @@ package metrics import ( "context" - "github.com/coredns/coredns/plugin/metrics/vars" + "github.com/coredns/coredns/core/dnsserver" ) // WithServer returns the current server handling the request. It returns the @@ -15,4 +15,10 @@ import ( // Basic usage with a metric: // // .WithLabelValues(metrics.WithServer(ctx), labels..).Add(1) -func WithServer(ctx context.Context) string { return vars.WithServer(ctx) } +func WithServer(ctx context.Context) string { + srv := ctx.Value(dnsserver.Key{}) + if srv == nil { + return "" + } + return srv.(*dnsserver.Server).Addr +} diff --git a/vendor/github.com/coredns/coredns/plugin/metrics/handler.go b/vendor/github.com/coredns/coredns/plugin/metrics/handler.go index 71132c274..0dbc053da 100644 --- a/vendor/github.com/coredns/coredns/plugin/metrics/handler.go +++ b/vendor/github.com/coredns/coredns/plugin/metrics/handler.go @@ -26,7 +26,7 @@ func (m *Metrics) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg rw := dnstest.NewRecorder(w) status, err := plugin.NextOrFailure(m.Name(), m.Next, ctx, rw, r) - vars.Report(ctx, state, zone, rcode.ToString(rw.Rcode), rw.Len, rw.Start) + vars.Report(WithServer(ctx), state, zone, rcode.ToString(rw.Rcode), rw.Len, rw.Start) return status, err } diff --git a/vendor/github.com/coredns/coredns/plugin/metrics/metrics.go b/vendor/github.com/coredns/coredns/plugin/metrics/metrics.go index 6b496cccc..89c948aa6 100644 --- a/vendor/github.com/coredns/coredns/plugin/metrics/metrics.go +++ b/vendor/github.com/coredns/coredns/plugin/metrics/metrics.go @@ -5,7 +5,6 @@ import ( "context" "net" "net/http" - "os" "sync" "time" @@ -27,7 +26,7 @@ type Metrics struct { srv *http.Server zoneNames []string - zoneMap map[string]bool + zoneMap map[string]struct{} zoneMu sync.RWMutex } @@ -36,11 +35,11 @@ func New(addr string) *Metrics { met := &Metrics{ Addr: addr, Reg: prometheus.NewRegistry(), - zoneMap: make(map[string]bool), + zoneMap: make(map[string]struct{}), } // Add the default collectors met.MustRegister(prometheus.NewGoCollector()) - met.MustRegister(prometheus.NewProcessCollector(os.Getpid(), "")) + met.MustRegister(prometheus.NewProcessCollector(prometheus.ProcessCollectorOpts{})) // Add all of our collectors met.MustRegister(buildInfo) @@ -52,6 +51,7 @@ func New(addr string) *Metrics { met.MustRegister(vars.RequestType) met.MustRegister(vars.ResponseSize) met.MustRegister(vars.ResponseRcode) + met.MustRegister(vars.PluginEnabled) return met } @@ -70,7 +70,7 @@ func (m *Metrics) MustRegister(c prometheus.Collector) { // AddZone adds zone z to m. func (m *Metrics) AddZone(z string) { m.zoneMu.Lock() - m.zoneMap[z] = true + m.zoneMap[z] = struct{}{} m.zoneNames = keys(m.zoneMap) m.zoneMu.Unlock() } @@ -141,7 +141,7 @@ func (m *Metrics) OnFinalShutdown() error { return m.stopServer() } -func keys(m map[string]bool) []string { +func keys(m map[string]struct{}) []string { sx := []string{} for k := range m { sx = append(sx, k) diff --git a/vendor/github.com/coredns/coredns/plugin/metrics/setup.go b/vendor/github.com/coredns/coredns/plugin/metrics/setup.go index ffc0466f3..b50960211 100644 --- a/vendor/github.com/coredns/coredns/plugin/metrics/setup.go +++ b/vendor/github.com/coredns/coredns/plugin/metrics/setup.go @@ -7,6 +7,7 @@ import ( "github.com/coredns/coredns/core/dnsserver" "github.com/coredns/coredns/coremain" "github.com/coredns/coredns/plugin" + "github.com/coredns/coredns/plugin/metrics/vars" clog "github.com/coredns/coredns/plugin/pkg/log" "github.com/coredns/coredns/plugin/pkg/uniq" @@ -50,6 +51,23 @@ func setup(c *caddy.Controller) error { return nil }) + c.OnRestart(func() error { + vars.PluginEnabled.Reset() + return nil + }) + + c.OnStartup(func() error { + conf := dnsserver.GetConfig(c) + plugins := conf.Handlers() + for _, h := range conf.ListenHosts { + addrstr := conf.Transport + "://" + net.JoinHostPort(h, conf.Port) + for _, p := range plugins { + vars.PluginEnabled.WithLabelValues(addrstr, conf.Zone, p.Name()).Set(1) + } + } + return nil + + }) c.OnRestart(m.OnRestart) c.OnFinalShutdown(m.OnFinalShutdown) diff --git a/vendor/github.com/coredns/coredns/plugin/metrics/vars/report.go b/vendor/github.com/coredns/coredns/plugin/metrics/vars/report.go index d0c64b864..343d98a22 100644 --- a/vendor/github.com/coredns/coredns/plugin/metrics/vars/report.go +++ b/vendor/github.com/coredns/coredns/plugin/metrics/vars/report.go @@ -1,17 +1,17 @@ package vars import ( - "context" "time" - "github.com/coredns/coredns/plugin" "github.com/coredns/coredns/request" "github.com/miekg/dns" ) -// Report reports the metrics data associated with request. -func Report(ctx context.Context, req request.Request, zone, rcode string, size int, start time.Time) { +// Report reports the metrics data associated with request. This function is exported because it is also +// called from core/dnsserver to report requests hitting the server that should not be handled and are thus +// not sent down the plugin chain. +func Report(server string, req request.Request, zone, rcode string, size int, start time.Time) { // Proto and Family. net := req.Proto() fam := "1" @@ -19,8 +19,6 @@ func Report(ctx context.Context, req request.Request, zone, rcode string, size i fam = "2" } - server := WithServer(ctx) - typ := req.QType() RequestCount.WithLabelValues(server, zone, net, fam).Inc() RequestDuration.WithLabelValues(server, zone).Observe(time.Since(start).Seconds()) @@ -41,34 +39,25 @@ func Report(ctx context.Context, req request.Request, zone, rcode string, size i ResponseRcode.WithLabelValues(server, zone, rcode).Inc() } -// WithServer returns the current server handling the request. -func WithServer(ctx context.Context) string { - srv := ctx.Value(plugin.ServerCtx{}) - if srv == nil { - return "" - } - return srv.(string) -} - -var monitorType = map[uint16]bool{ - dns.TypeAAAA: true, - dns.TypeA: true, - dns.TypeCNAME: true, - dns.TypeDNSKEY: true, - dns.TypeDS: true, - dns.TypeMX: true, - dns.TypeNSEC3: true, - dns.TypeNSEC: true, - dns.TypeNS: true, - dns.TypePTR: true, - dns.TypeRRSIG: true, - dns.TypeSOA: true, - dns.TypeSRV: true, - dns.TypeTXT: true, +var monitorType = map[uint16]struct{}{ + dns.TypeAAAA: struct{}{}, + dns.TypeA: struct{}{}, + dns.TypeCNAME: struct{}{}, + dns.TypeDNSKEY: struct{}{}, + dns.TypeDS: struct{}{}, + dns.TypeMX: struct{}{}, + dns.TypeNSEC3: struct{}{}, + dns.TypeNSEC: struct{}{}, + dns.TypeNS: struct{}{}, + dns.TypePTR: struct{}{}, + dns.TypeRRSIG: struct{}{}, + dns.TypeSOA: struct{}{}, + dns.TypeSRV: struct{}{}, + dns.TypeTXT: struct{}{}, // Meta Qtypes - dns.TypeIXFR: true, - dns.TypeAXFR: true, - dns.TypeANY: true, + dns.TypeIXFR: struct{}{}, + dns.TypeAXFR: struct{}{}, + dns.TypeANY: struct{}{}, } const other = "other" diff --git a/vendor/github.com/coredns/coredns/plugin/metrics/vars/vars.go b/vendor/github.com/coredns/coredns/plugin/metrics/vars/vars.go index a25a0894c..3adee1d76 100644 --- a/vendor/github.com/coredns/coredns/plugin/metrics/vars/vars.go +++ b/vendor/github.com/coredns/coredns/plugin/metrics/vars/vars.go @@ -65,6 +65,12 @@ var ( Name: "panic_count_total", Help: "A metrics that counts the number of panics.", }) + + PluginEnabled = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Namespace: plugin.Namespace, + Name: "plugin_enabled", + Help: "A metric that indicates whether a plugin is enabled on per server and zone basis.", + }, []string{"server", "zone", "name"}) ) const ( diff --git a/vendor/github.com/coredns/coredns/plugin/normalize.go b/vendor/github.com/coredns/coredns/plugin/normalize.go index dc295ce01..6402bf8d9 100644 --- a/vendor/github.com/coredns/coredns/plugin/normalize.go +++ b/vendor/github.com/coredns/coredns/plugin/normalize.go @@ -15,8 +15,8 @@ import ( // Zones respresents a lists of zone names. type Zones []string -// Matches checks is qname is a subdomain of any of the zones in z. The match -// will return the most specific zones that matches other. The empty string +// Matches checks if qname is a subdomain of any of the zones in z. The match +// will return the most specific zones that matches. The empty string // signals a not found condition. func (z Zones) Matches(qname string) string { zone := "" diff --git a/vendor/github.com/coredns/coredns/plugin/pkg/edns/edns.go b/vendor/github.com/coredns/coredns/plugin/pkg/edns/edns.go index 3f0ea5e16..68fb03865 100644 --- a/vendor/github.com/coredns/coredns/plugin/pkg/edns/edns.go +++ b/vendor/github.com/coredns/coredns/plugin/pkg/edns/edns.go @@ -3,10 +3,37 @@ package edns import ( "errors" + "sync" "github.com/miekg/dns" ) +var sup = &supported{m: make(map[uint16]struct{})} + +type supported struct { + m map[uint16]struct{} + sync.RWMutex +} + +// SetSupportedOption adds a new supported option the set of EDNS0 options that we support. Plugins typically call +// this in their setup code to signal support for a new option. +// By default we support: +// dns.EDNS0NSID, dns.EDNS0EXPIRE, dns.EDNS0COOKIE, dns.EDNS0TCPKEEPALIVE, dns.EDNS0PADDING. These +// values are not in this map and checked directly in the server. +func SetSupportedOption(option uint16) { + sup.Lock() + sup.m[option] = struct{}{} + sup.Unlock() +} + +// SupportedOption returns true if the option code is supported as an extra EDNS0 option. +func SupportedOption(option uint16) bool { + sup.RLock() + _, ok := sup.m[option] + sup.RUnlock() + return ok +} + // Version checks the EDNS version in the request. If error // is nil everything is OK and we can invoke the plugin. If non-nil, the // returned Msg is valid to be returned to the client (and should). For some @@ -28,6 +55,7 @@ func Version(req *dns.Msg) (*dns.Msg, error) { o.Hdr.Name = "." o.Hdr.Rrtype = dns.TypeOPT o.SetVersion(0) + m.Rcode = dns.RcodeBadVers o.SetExtendedRcode(dns.RcodeBadVers) m.Extra = []dns.RR{o} diff --git a/vendor/github.com/coredns/coredns/plugin/pkg/log/log.go b/vendor/github.com/coredns/coredns/plugin/pkg/log/log.go index 2c8971e1d..b4bd1cad8 100644 --- a/vendor/github.com/coredns/coredns/plugin/pkg/log/log.go +++ b/vendor/github.com/coredns/coredns/plugin/pkg/log/log.go @@ -20,7 +20,7 @@ import ( var D bool // RFC3339Milli doesn't exist, invent it here. -func clock() string { return time.Now().Format("2006-01-02T15:04:05.999Z07:00") } +func clock() string { return time.Now().Format("2006-01-02T15:04:05.000Z07:00") } // logf calls log.Printf prefixed with level. func logf(level, format string, v ...interface{}) { diff --git a/vendor/github.com/coredns/coredns/plugin/pkg/log/plugin.go b/vendor/github.com/coredns/coredns/plugin/pkg/log/plugin.go index 1df302609..0cc5f881a 100644 --- a/vendor/github.com/coredns/coredns/plugin/pkg/log/plugin.go +++ b/vendor/github.com/coredns/coredns/plugin/pkg/log/plugin.go @@ -2,7 +2,6 @@ package log import ( "fmt" - golog "log" "os" ) @@ -13,16 +12,14 @@ type P struct { // NewWithPlugin returns a logger that includes "plugin/name: " in the log message. // I.e [INFO] plugin/: message. -func NewWithPlugin(name string) P { return P{name} } +func NewWithPlugin(name string) P { return P{"plugin/" + name + ": "} } func (p P) logf(level, format string, v ...interface{}) { - s := level + pFormat(p.plugin) + fmt.Sprintf(format, v...) - golog.Print(s) + log(level, p.plugin, fmt.Sprintf(format, v...)) } func (p P) log(level string, v ...interface{}) { - s := level + pFormat(p.plugin) + fmt.Sprint(v...) - golog.Print(s) + log(level+p.plugin, v...) } // Debug logs as log.Debug. @@ -64,5 +61,3 @@ func (p P) Fatal(v ...interface{}) { p.log(fatal, v...); os.Exit(1) } // Fatalf logs as log.Fatalf and calls os.Exit(1). func (p P) Fatalf(format string, v ...interface{}) { p.logf(fatal, format, v...); os.Exit(1) } - -func pFormat(s string) string { return "plugin/" + s + ": " } diff --git a/vendor/github.com/coredns/coredns/plugin/pkg/replacer/replacer.go b/vendor/github.com/coredns/coredns/plugin/pkg/replacer/replacer.go index 695e9e392..3e2cbfcbd 100644 --- a/vendor/github.com/coredns/coredns/plugin/pkg/replacer/replacer.go +++ b/vendor/github.com/coredns/coredns/plugin/pkg/replacer/replacer.go @@ -1,107 +1,146 @@ package replacer import ( + "context" "strconv" "strings" "time" + "github.com/coredns/coredns/plugin/metadata" "github.com/coredns/coredns/plugin/pkg/dnstest" "github.com/coredns/coredns/request" "github.com/miekg/dns" ) -// Replacer is a type which can replace placeholder -// substrings in a string with actual values from a -// dns.Msg and responseRecorder. Always use -// NewReplacer to get one of these. -type Replacer interface { - Replace(string) string - Set(key, value string) +// Replacer replaces labels for values in strings. +type Replacer struct { + valueFunc func(request.Request, *dnstest.Recorder, string) string + labels []string } -type replacer struct { - replacements map[string]string - emptyValue string +// labels are all supported labels that can be used in the default Replacer. +var labels = []string{ + "{type}", + "{name}", + "{class}", + "{proto}", + "{size}", + "{remote}", + "{port}", + "{local}", + // Header values. + headerReplacer + "id}", + headerReplacer + "opcode}", + headerReplacer + "do}", + headerReplacer + "bufsize}", + // Recorded replacements. + "{rcode}", + "{rsize}", + "{duration}", + headerReplacer + "rflags}", } -// New makes a new replacer based on r and rr. -// Do not create a new replacer until r and rr have all -// the needed values, because this function copies those -// values into the replacer. rr may be nil if it is not -// available. emptyValue should be the string that is used -// in place of empty string (can still be empty string). -func New(r *dns.Msg, rr *dnstest.Recorder, emptyValue string) Replacer { - req := request.Request{W: rr, Req: r} - rep := replacer{ - replacements: map[string]string{ - "{type}": req.Type(), - "{name}": req.Name(), - "{class}": req.Class(), - "{proto}": req.Proto(), - "{when}": "", // made a noop - "{size}": strconv.Itoa(req.Len()), - "{remote}": addrToRFC3986(req.IP()), - "{port}": req.Port(), - }, - emptyValue: emptyValue, - } - if rr != nil { +// value returns the current value of label. +func value(state request.Request, rr *dnstest.Recorder, label string) string { + switch label { + case "{type}": + return state.Type() + case "{name}": + return state.Name() + case "{class}": + return state.Class() + case "{proto}": + return state.Proto() + case "{size}": + return strconv.Itoa(state.Req.Len()) + case "{remote}": + return addrToRFC3986(state.IP()) + case "{port}": + return state.Port() + case "{local}": + return addrToRFC3986(state.LocalIP()) + // Header placeholders (case-insensitive). + case headerReplacer + "id}": + return strconv.Itoa(int(state.Req.Id)) + case headerReplacer + "opcode}": + return strconv.Itoa(state.Req.Opcode) + case headerReplacer + "do}": + return boolToString(state.Do()) + case headerReplacer + "bufsize}": + return strconv.Itoa(state.Size()) + // Recorded replacements. + case "{rcode}": + if rr == nil { + return EmptyValue + } rcode := dns.RcodeToString[rr.Rcode] if rcode == "" { rcode = strconv.Itoa(rr.Rcode) } - rep.replacements["{rcode}"] = rcode - rep.replacements["{rsize}"] = strconv.Itoa(rr.Len) - rep.replacements["{duration}"] = strconv.FormatFloat(time.Since(rr.Start).Seconds(), 'f', -1, 64) + "s" - if rr.Msg != nil { - rep.replacements[headerReplacer+"rflags}"] = flagsToString(rr.Msg.MsgHdr) + return rcode + case "{rsize}": + if rr == nil { + return EmptyValue + } + return strconv.Itoa(rr.Len) + case "{duration}": + if rr == nil { + return EmptyValue } + return strconv.FormatFloat(time.Since(rr.Start).Seconds(), 'f', -1, 64) + "s" + case headerReplacer + "rflags}": + if rr != nil && rr.Msg != nil { + return flagsToString(rr.Msg.MsgHdr) + } + return EmptyValue } + return EmptyValue +} - // Header placeholders (case-insensitive) - rep.replacements[headerReplacer+"id}"] = strconv.Itoa(int(r.Id)) - rep.replacements[headerReplacer+"opcode}"] = strconv.Itoa(r.Opcode) - rep.replacements[headerReplacer+"do}"] = boolToString(req.Do()) - rep.replacements[headerReplacer+"bufsize}"] = strconv.Itoa(req.Size()) - - return rep +// New makes a new replacer. This only needs to be called once in the setup and then call Replace for each incoming message. +// A replacer is safe for concurrent use. +func New() Replacer { + return Replacer{ + valueFunc: value, + labels: labels, + } } -// Replace performs a replacement of values on s and returns -// the string with the replaced values. -func (r replacer) Replace(s string) string { - // Header replacements - these are case-insensitive, so we can't just use strings.Replace() - for strings.Contains(s, headerReplacer) { - idxStart := strings.Index(s, headerReplacer) - endOffset := idxStart + len(headerReplacer) +// Replace performs a replacement of values on s and returns the string with the replaced values. +func (r Replacer) Replace(ctx context.Context, state request.Request, rr *dnstest.Recorder, s string) string { + for _, placeholder := range r.labels { + if strings.Contains(s, placeholder) { + s = strings.Replace(s, placeholder, r.valueFunc(state, rr, placeholder), -1) + } + } + + // Metadata label replacements. Scan for {/ and search for next }, replace that metadata label with + // any meta data that is available. + b := strings.Builder{} + for strings.Contains(s, labelReplacer) { + idxStart := strings.Index(s, labelReplacer) + endOffset := idxStart + len(labelReplacer) idxEnd := strings.Index(s[endOffset:], "}") if idxEnd > -1 { - placeholder := strings.ToLower(s[idxStart : endOffset+idxEnd+1]) - replacement := r.replacements[placeholder] - if replacement == "" { - replacement = r.emptyValue + label := s[idxStart+2 : endOffset+idxEnd] + + fm := metadata.ValueFunc(ctx, label) + replacement := EmptyValue + if fm != nil { + replacement = fm() } - s = s[:idxStart] + replacement + s[endOffset+idxEnd+1:] + + b.WriteString(s[:idxStart]) + b.WriteString(replacement) + s = s[endOffset+idxEnd+1:] } else { break } } - // Regular replacements - these are easier because they're case-sensitive - for placeholder, replacement := range r.replacements { - if replacement == "" { - replacement = r.emptyValue - } - s = strings.Replace(s, placeholder, replacement, -1) - } - - return s -} - -// Set sets key to value in the replacements map. -func (r replacer) Set(key, value string) { - r.replacements["{"+key+"}"] = value + b.WriteString(s) + return b.String() } func boolToString(b bool) string { @@ -161,4 +200,9 @@ func addrToRFC3986(addr string) string { return addr } -const headerReplacer = "{>" +const ( + headerReplacer = "{>" + labelReplacer = "{/" + // EmptyValue is the default empty value. + EmptyValue = "-" +) diff --git a/vendor/github.com/coredns/coredns/plugin/pkg/up/up.go b/vendor/github.com/coredns/coredns/plugin/pkg/up/up.go index e2c9fe2cd..8f866311b 100644 --- a/vendor/github.com/coredns/coredns/plugin/pkg/up/up.go +++ b/vendor/github.com/coredns/coredns/plugin/pkg/up/up.go @@ -9,10 +9,12 @@ import ( // Probe is used to run a single Func until it returns true (indicating a target is healthy). If an Func // is already in progress no new one will be added, i.e. there is always a maximum of 1 checks in flight. +// When failures start to happen we will back off every second failure up to maximum of 4 intervals. type Probe struct { sync.Mutex inprogress int interval time.Duration + max time.Duration } // Func is used to determine if a target is alive. If so this function must return nil. @@ -34,17 +36,22 @@ func (p *Probe) Do(f Func) { // Passed the lock. Now run f for as long it returns false. If a true is returned // we return from the goroutine and we can accept another Func to run. go func() { + i := 1 for { if err := f(); err == nil { break } time.Sleep(interval) + if i%2 == 0 && i < 4 { // 4 is 2 doubles, so no need to increase anymore - this is *also* checked in double() + p.double() + } p.Lock() if p.inprogress == stop { p.Unlock() return } p.Unlock() + i++ } p.Lock() @@ -53,6 +60,15 @@ func (p *Probe) Do(f Func) { }() } +func (p *Probe) double() { + p.Lock() + p.interval *= 2 + if p.interval > p.max { + p.interval = p.max + } + p.Unlock() +} + // Stop stops the probing. func (p *Probe) Stop() { p.Lock() @@ -61,12 +77,10 @@ func (p *Probe) Stop() { } // Start will initialize the probe manager, after which probes can be initiated with Do. -func (p *Probe) Start(interval time.Duration) { p.SetInterval(interval) } - -// SetInterval sets the probing interval to be used by upcoming probes initiated with Do. -func (p *Probe) SetInterval(interval time.Duration) { +func (p *Probe) Start(interval time.Duration) { p.Lock() p.interval = interval + p.max = interval * multiplier p.Unlock() } @@ -74,4 +88,6 @@ const ( idle = iota active stop + + multiplier = 4 ) diff --git a/vendor/github.com/coredns/coredns/plugin/pkg/watch/watch.go b/vendor/github.com/coredns/coredns/plugin/pkg/watch/watch.go deleted file mode 100644 index 7e77bb7b3..000000000 --- a/vendor/github.com/coredns/coredns/plugin/pkg/watch/watch.go +++ /dev/null @@ -1,23 +0,0 @@ -package watch - -// Chan is used to inform the server of a change. Whenever -// a watched FQDN has a change in data, that FQDN should be -// sent down this channel. -type Chan chan string - -// Watchable is the interface watchable plugins should implement -type Watchable interface { - // Name returns the plugin name. - Name() string - - // SetWatchChan is called when the watch channel is created. - SetWatchChan(Chan) - - // Watch is called whenever a watch is created for a FQDN. Plugins - // should send the FQDN down the watch channel when its data may have - // changed. This is an exact match only. - Watch(qname string) error - - // StopWatching is called whenever all watches are canceled for a FQDN. - StopWatching(qname string) -} diff --git a/vendor/github.com/coredns/coredns/plugin/pkg/watch/watcher.go b/vendor/github.com/coredns/coredns/plugin/pkg/watch/watcher.go deleted file mode 100644 index 86a952db2..000000000 --- a/vendor/github.com/coredns/coredns/plugin/pkg/watch/watcher.go +++ /dev/null @@ -1,178 +0,0 @@ -package watch - -import ( - "fmt" - "io" - "sync" - - "github.com/miekg/dns" - - "github.com/coredns/coredns/pb" - "github.com/coredns/coredns/plugin" - "github.com/coredns/coredns/plugin/pkg/log" - "github.com/coredns/coredns/request" -) - -// Watcher handles watch creation, cancellation, and processing. -type Watcher interface { - // Watch monitors a client stream and creates and cancels watches. - Watch(pb.DnsService_WatchServer) error - - // Stop cancels open watches and stops the watch processing go routine. - Stop() -} - -// Manager contains all the data needed to manage watches -type Manager struct { - changes Chan - stopper chan bool - counter int64 - watches map[string]watchlist - plugins []Watchable - mutex sync.Mutex -} - -type watchlist map[int64]pb.DnsService_WatchServer - -// NewWatcher creates a Watcher, which is used to manage watched names. -func NewWatcher(plugins []Watchable) *Manager { - w := &Manager{changes: make(Chan), stopper: make(chan bool), watches: make(map[string]watchlist), plugins: plugins} - - for _, p := range plugins { - p.SetWatchChan(w.changes) - } - - go w.process() - return w -} - -func (w *Manager) nextID() int64 { - w.mutex.Lock() - - w.counter++ - id := w.counter - - w.mutex.Unlock() - return id -} - -// Watch monitors a client stream and creates and cancels watches. -func (w *Manager) Watch(stream pb.DnsService_WatchServer) error { - for { - in, err := stream.Recv() - if err == io.EOF { - return nil - } - if err != nil { - return err - } - create := in.GetCreateRequest() - if create != nil { - msg := new(dns.Msg) - err := msg.Unpack(create.Query.Msg) - if err != nil { - log.Warningf("Could not decode watch request: %s\n", err) - stream.Send(&pb.WatchResponse{Err: "could not decode request"}) - continue - } - id := w.nextID() - if err := stream.Send(&pb.WatchResponse{WatchId: id, Created: true}); err != nil { - // if we fail to notify client of watch creation, don't create the watch - continue - } - - // Normalize qname - qname := (&request.Request{Req: msg}).Name() - - w.mutex.Lock() - if _, ok := w.watches[qname]; !ok { - w.watches[qname] = make(watchlist) - } - w.watches[qname][id] = stream - w.mutex.Unlock() - - for _, p := range w.plugins { - err := p.Watch(qname) - if err != nil { - log.Warningf("Failed to start watch for %s in plugin %s: %s\n", qname, p.Name(), err) - stream.Send(&pb.WatchResponse{Err: fmt.Sprintf("failed to start watch for %s in plugin %s", qname, p.Name())}) - } - } - continue - } - - cancel := in.GetCancelRequest() - if cancel != nil { - w.mutex.Lock() - for qname, wl := range w.watches { - ws, ok := wl[cancel.WatchId] - if !ok { - continue - } - - // only allow cancels from the client that started it - // TODO: test what happens if a stream tries to cancel a watchID that it doesn't own - if ws != stream { - continue - } - - delete(wl, cancel.WatchId) - - // if there are no more watches for this qname, we should tell the plugins - if len(wl) == 0 { - for _, p := range w.plugins { - p.StopWatching(qname) - } - delete(w.watches, qname) - } - - // let the client know we canceled the watch - stream.Send(&pb.WatchResponse{WatchId: cancel.WatchId, Canceled: true}) - } - w.mutex.Unlock() - continue - } - } -} - -func (w *Manager) process() { - for { - select { - case <-w.stopper: - return - case changed := <-w.changes: - w.mutex.Lock() - for qname, wl := range w.watches { - if plugin.Zones([]string{changed}).Matches(qname) == "" { - continue - } - for id, stream := range wl { - wr := pb.WatchResponse{WatchId: id, Qname: qname} - err := stream.Send(&wr) - if err != nil { - log.Warningf("Error sending change for %s to watch %d: %s. Removing watch.\n", qname, id, err) - delete(w.watches[qname], id) - } - } - } - w.mutex.Unlock() - } - } -} - -// Stop cancels open watches and stops the watch processing go routine. -func (w *Manager) Stop() { - w.stopper <- true - w.mutex.Lock() - for wn, wl := range w.watches { - for id, stream := range wl { - wr := pb.WatchResponse{WatchId: id, Canceled: true} - err := stream.Send(&wr) - if err != nil { - log.Warningf("Error notifying client of cancellation: %s\n", err) - } - } - delete(w.watches, wn) - } - w.mutex.Unlock() -} diff --git a/vendor/github.com/coredns/coredns/plugin/plugin.go b/vendor/github.com/coredns/coredns/plugin/plugin.go index 65bf939f1..4a4448f62 100644 --- a/vendor/github.com/coredns/coredns/plugin/plugin.go +++ b/vendor/github.com/coredns/coredns/plugin/plugin.go @@ -68,7 +68,7 @@ func (f HandlerFunc) Name() string { return "handlerfunc" } // Error returns err with 'plugin/name: ' prefixed to it. func Error(name string, err error) error { return fmt.Errorf("%s/%s: %s", "plugin", name, err) } -// NextOrFailure calls next.ServeDNS when next is not nill, otherwise it will return, a ServerFailure and a nil error. +// NextOrFailure calls next.ServeDNS when next is not nil, otherwise it will return, a ServerFailure and a nil error. func NextOrFailure(name string, next Handler, ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { // nolint: golint if next != nil { if span := ot.SpanFromContext(ctx); span != nil { @@ -106,6 +106,3 @@ var TimeBuckets = prometheus.ExponentialBuckets(0.00025, 2, 16) // from 0.25ms t // ErrOnce is returned when a plugin doesn't support multiple setups per server. var ErrOnce = errors.New("this plugin can only be used once per Server Block") - -// ServerCtx is the context key to pass server address context to the plugins handling the request. -type ServerCtx struct{} diff --git a/vendor/github.com/coredns/coredns/plugin/reload/README.md b/vendor/github.com/coredns/coredns/plugin/reload/README.md index 625e4b025..8d1f5db64 100644 --- a/vendor/github.com/coredns/coredns/plugin/reload/README.md +++ b/vendor/github.com/coredns/coredns/plugin/reload/README.md @@ -88,3 +88,10 @@ After the aborted attempt to reload we are left with the old processes running, closed in step 1; so the health endpoint is broken. The same can hopen in the prometheus metrics plugin. In general be careful with assigning new port and expecting reload to work fully. + +Also any `import` statement is not discovered by this plugin. This means if any of these imported files +changes the *reload* plugin is ignorant of that fact. + +## Also See + +See coredns-import(7) and corefile(5). diff --git a/vendor/github.com/coredns/coredns/plugin/reload/reload.go b/vendor/github.com/coredns/coredns/plugin/reload/reload.go index d04bb037b..3abc33835 100644 --- a/vendor/github.com/coredns/coredns/plugin/reload/reload.go +++ b/vendor/github.com/coredns/coredns/plugin/reload/reload.go @@ -2,6 +2,7 @@ package reload import ( "crypto/md5" + "sync" "time" "github.com/mholt/caddy" @@ -15,9 +16,34 @@ const ( ) type reload struct { - interval time.Duration - usage int - quit chan bool + dur time.Duration + u int + mtx sync.RWMutex + quit chan bool +} + +func (r *reload) setUsage(u int) { + r.mtx.Lock() + defer r.mtx.Unlock() + r.u = u +} + +func (r *reload) usage() int { + r.mtx.RLock() + defer r.mtx.RUnlock() + return r.u +} + +func (r *reload) setInterval(i time.Duration) { + r.mtx.Lock() + defer r.mtx.Unlock() + r.dur = i +} + +func (r *reload) interval() time.Duration { + r.mtx.RLock() + defer r.mtx.RUnlock() + return r.dur } func hook(event caddy.EventName, info interface{}) error { @@ -28,7 +54,7 @@ func hook(event caddy.EventName, info interface{}) error { // if reload is removed from the Corefile, then the hook // is still registered but setup is never called again // so we need a flag to tell us not to reload - if r.usage == unused { + if r.usage() == unused { return nil } @@ -38,7 +64,7 @@ func hook(event caddy.EventName, info interface{}) error { log.Infof("Running configuration MD5 = %x\n", md5sum) go func() { - tick := time.NewTicker(r.interval) + tick := time.NewTicker(r.interval()) for { select { @@ -53,15 +79,15 @@ func hook(event caddy.EventName, info interface{}) error { md5sum = s // now lets consider that plugin will not be reload, unless appear in next config file // change status iof usage will be reset in setup if the plugin appears in config file - r.usage = maybeUsed + r.setUsage(maybeUsed) _, err := instance.Restart(corefile) if err != nil { - log.Errorf("Corefile changed but reload failed: %s\n", err) + log.Errorf("Corefile changed but reload failed: %s", err) continue } // we are done, if the plugin was not set used, then it is not. - if r.usage == maybeUsed { - r.usage = unused + if r.usage() == maybeUsed { + r.setUsage(unused) } return } diff --git a/vendor/github.com/coredns/coredns/plugin/reload/setup.go b/vendor/github.com/coredns/coredns/plugin/reload/setup.go index c6b33e959..ed4d9f85d 100644 --- a/vendor/github.com/coredns/coredns/plugin/reload/setup.go +++ b/vendor/github.com/coredns/coredns/plugin/reload/setup.go @@ -25,9 +25,10 @@ func init() { // it is used to transmit data between Setup and start of the hook called 'onInstanceStartup' // channel for QUIT is never changed in purpose. // WARNING: this data may be unsync after an invalid attempt of reload Corefile. -var r = reload{interval: defaultInterval, usage: unused, quit: make(chan bool)} -var once sync.Once -var shutOnce sync.Once +var ( + r = reload{dur: defaultInterval, u: unused, quit: make(chan bool)} + once, shutOnce sync.Once +) func setup(c *caddy.Controller) error { c.Next() // 'reload' @@ -69,8 +70,8 @@ func setup(c *caddy.Controller) error { i = i + jitter // prepare info for next onInstanceStartup event - r.interval = i - r.usage = used + r.setInterval(i) + r.setUsage(used) once.Do(func() { caddy.RegisterEventHook("reload", hook) diff --git a/vendor/github.com/coredns/coredns/plugin/test/helpers.go b/vendor/github.com/coredns/coredns/plugin/test/helpers.go index 70159e99a..eff5ed550 100644 --- a/vendor/github.com/coredns/coredns/plugin/test/helpers.go +++ b/vendor/github.com/coredns/coredns/plugin/test/helpers.go @@ -2,8 +2,8 @@ package test import ( "context" + "fmt" "sort" - "testing" "github.com/miekg/dns" ) @@ -113,29 +113,25 @@ func OPT(bufsize int, do bool) *dns.OPT { } // Header test if the header in resp matches the header as defined in tc. -func Header(t *testing.T, tc Case, resp *dns.Msg) bool { +func Header(tc Case, resp *dns.Msg) error { if resp.Rcode != tc.Rcode { - t.Errorf("Rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode]) - return false + return fmt.Errorf("rcode is %q, expected %q", dns.RcodeToString[resp.Rcode], dns.RcodeToString[tc.Rcode]) } if len(resp.Answer) != len(tc.Answer) { - t.Errorf("Answer for %q contained %d results, %d expected", tc.Qname, len(resp.Answer), len(tc.Answer)) - return false + return fmt.Errorf("answer for %q contained %d results, %d expected", tc.Qname, len(resp.Answer), len(tc.Answer)) } if len(resp.Ns) != len(tc.Ns) { - t.Errorf("Authority for %q contained %d results, %d expected", tc.Qname, len(resp.Ns), len(tc.Ns)) - return false + return fmt.Errorf("authority for %q contained %d results, %d expected", tc.Qname, len(resp.Ns), len(tc.Ns)) } if len(resp.Extra) != len(tc.Extra) { - t.Errorf("Additional for %q contained %d results, %d expected", tc.Qname, len(resp.Extra), len(tc.Extra)) - return false + return fmt.Errorf("additional for %q contained %d results, %d expected", tc.Qname, len(resp.Extra), len(tc.Extra)) } - return true + return nil } -// Section tests if the the section in tc matches rr. -func Section(t *testing.T, tc Case, sec sect, rr []dns.RR) bool { +// Section tests if the section in tc matches rr. +func Section(tc Case, sec sect, rr []dns.RR) error { section := []dns.RR{} switch sec { case 0: @@ -148,134 +144,112 @@ func Section(t *testing.T, tc Case, sec sect, rr []dns.RR) bool { for i, a := range rr { if a.Header().Name != section[i].Header().Name { - t.Errorf("RR %d should have a Header Name of %q, but has %q", i, section[i].Header().Name, a.Header().Name) - return false + return fmt.Errorf("RR %d should have a Header Name of %q, but has %q", i, section[i].Header().Name, a.Header().Name) } // 303 signals: don't care what the ttl is. if section[i].Header().Ttl != 303 && a.Header().Ttl != section[i].Header().Ttl { if _, ok := section[i].(*dns.OPT); !ok { // we check edns0 bufize on this one - t.Errorf("RR %d should have a Header TTL of %d, but has %d", i, section[i].Header().Ttl, a.Header().Ttl) - return false + return fmt.Errorf("RR %d should have a Header TTL of %d, but has %d", i, section[i].Header().Ttl, a.Header().Ttl) } } if a.Header().Rrtype != section[i].Header().Rrtype { - t.Errorf("RR %d should have a header rr type of %d, but has %d", i, section[i].Header().Rrtype, a.Header().Rrtype) - return false + return fmt.Errorf("RR %d should have a header rr type of %d, but has %d", i, section[i].Header().Rrtype, a.Header().Rrtype) } switch x := a.(type) { case *dns.SRV: if x.Priority != section[i].(*dns.SRV).Priority { - t.Errorf("RR %d should have a Priority of %d, but has %d", i, section[i].(*dns.SRV).Priority, x.Priority) - return false + return fmt.Errorf("RR %d should have a Priority of %d, but has %d", i, section[i].(*dns.SRV).Priority, x.Priority) } if x.Weight != section[i].(*dns.SRV).Weight { - t.Errorf("RR %d should have a Weight of %d, but has %d", i, section[i].(*dns.SRV).Weight, x.Weight) - return false + return fmt.Errorf("RR %d should have a Weight of %d, but has %d", i, section[i].(*dns.SRV).Weight, x.Weight) } if x.Port != section[i].(*dns.SRV).Port { - t.Errorf("RR %d should have a Port of %d, but has %d", i, section[i].(*dns.SRV).Port, x.Port) - return false + return fmt.Errorf("RR %d should have a Port of %d, but has %d", i, section[i].(*dns.SRV).Port, x.Port) } if x.Target != section[i].(*dns.SRV).Target { - t.Errorf("RR %d should have a Target of %q, but has %q", i, section[i].(*dns.SRV).Target, x.Target) - return false + return fmt.Errorf("RR %d should have a Target of %q, but has %q", i, section[i].(*dns.SRV).Target, x.Target) } case *dns.RRSIG: if x.TypeCovered != section[i].(*dns.RRSIG).TypeCovered { - t.Errorf("RR %d should have a TypeCovered of %d, but has %d", i, section[i].(*dns.RRSIG).TypeCovered, x.TypeCovered) - return false + return fmt.Errorf("RR %d should have a TypeCovered of %d, but has %d", i, section[i].(*dns.RRSIG).TypeCovered, x.TypeCovered) } if x.Labels != section[i].(*dns.RRSIG).Labels { - t.Errorf("RR %d should have a Labels of %d, but has %d", i, section[i].(*dns.RRSIG).Labels, x.Labels) - return false + return fmt.Errorf("RR %d should have a Labels of %d, but has %d", i, section[i].(*dns.RRSIG).Labels, x.Labels) } if x.SignerName != section[i].(*dns.RRSIG).SignerName { - t.Errorf("RR %d should have a SignerName of %s, but has %s", i, section[i].(*dns.RRSIG).SignerName, x.SignerName) - return false + return fmt.Errorf("RR %d should have a SignerName of %s, but has %s", i, section[i].(*dns.RRSIG).SignerName, x.SignerName) } case *dns.NSEC: if x.NextDomain != section[i].(*dns.NSEC).NextDomain { - t.Errorf("RR %d should have a NextDomain of %s, but has %s", i, section[i].(*dns.NSEC).NextDomain, x.NextDomain) - return false + return fmt.Errorf("RR %d should have a NextDomain of %s, but has %s", i, section[i].(*dns.NSEC).NextDomain, x.NextDomain) } // TypeBitMap case *dns.A: if x.A.String() != section[i].(*dns.A).A.String() { - t.Errorf("RR %d should have a Address of %q, but has %q", i, section[i].(*dns.A).A.String(), x.A.String()) - return false + return fmt.Errorf("RR %d should have a Address of %q, but has %q", i, section[i].(*dns.A).A.String(), x.A.String()) } case *dns.AAAA: if x.AAAA.String() != section[i].(*dns.AAAA).AAAA.String() { - t.Errorf("RR %d should have a Address of %q, but has %q", i, section[i].(*dns.AAAA).AAAA.String(), x.AAAA.String()) - return false + return fmt.Errorf("RR %d should have a Address of %q, but has %q", i, section[i].(*dns.AAAA).AAAA.String(), x.AAAA.String()) } case *dns.TXT: for j, txt := range x.Txt { if txt != section[i].(*dns.TXT).Txt[j] { - t.Errorf("RR %d should have a Txt of %q, but has %q", i, section[i].(*dns.TXT).Txt[j], txt) - return false + return fmt.Errorf("RR %d should have a Txt of %q, but has %q", i, section[i].(*dns.TXT).Txt[j], txt) } } case *dns.HINFO: if x.Cpu != section[i].(*dns.HINFO).Cpu { - t.Errorf("RR %d should have a Cpu of %s, but has %s", i, section[i].(*dns.HINFO).Cpu, x.Cpu) + return fmt.Errorf("RR %d should have a Cpu of %s, but has %s", i, section[i].(*dns.HINFO).Cpu, x.Cpu) } if x.Os != section[i].(*dns.HINFO).Os { - t.Errorf("RR %d should have a Os of %s, but has %s", i, section[i].(*dns.HINFO).Os, x.Os) + return fmt.Errorf("RR %d should have a Os of %s, but has %s", i, section[i].(*dns.HINFO).Os, x.Os) } case *dns.SOA: tt := section[i].(*dns.SOA) if x.Ns != tt.Ns { - t.Errorf("SOA nameserver should be %q, but is %q", tt.Ns, x.Ns) - return false + return fmt.Errorf("SOA nameserver should be %q, but is %q", tt.Ns, x.Ns) } case *dns.PTR: tt := section[i].(*dns.PTR) if x.Ptr != tt.Ptr { - t.Errorf("PTR ptr should be %q, but is %q", tt.Ptr, x.Ptr) - return false + return fmt.Errorf("PTR ptr should be %q, but is %q", tt.Ptr, x.Ptr) } case *dns.CNAME: tt := section[i].(*dns.CNAME) if x.Target != tt.Target { - t.Errorf("CNAME target should be %q, but is %q", tt.Target, x.Target) - return false + return fmt.Errorf("CNAME target should be %q, but is %q", tt.Target, x.Target) } case *dns.MX: tt := section[i].(*dns.MX) if x.Mx != tt.Mx { - t.Errorf("MX Mx should be %q, but is %q", tt.Mx, x.Mx) - return false + return fmt.Errorf("MX Mx should be %q, but is %q", tt.Mx, x.Mx) } if x.Preference != tt.Preference { - t.Errorf("MX Preference should be %q, but is %q", tt.Preference, x.Preference) - return false + return fmt.Errorf("MX Preference should be %q, but is %q", tt.Preference, x.Preference) } case *dns.NS: tt := section[i].(*dns.NS) if x.Ns != tt.Ns { - t.Errorf("NS nameserver should be %q, but is %q", tt.Ns, x.Ns) - return false + return fmt.Errorf("NS nameserver should be %q, but is %q", tt.Ns, x.Ns) } case *dns.OPT: tt := section[i].(*dns.OPT) if x.UDPSize() != tt.UDPSize() { - t.Errorf("OPT UDPSize should be %d, but is %d", tt.UDPSize(), x.UDPSize()) - return false + return fmt.Errorf("OPT UDPSize should be %d, but is %d", tt.UDPSize(), x.UDPSize()) } if x.Do() != tt.Do() { - t.Errorf("OPT DO should be %t, but is %t", tt.Do(), x.Do()) - return false + return fmt.Errorf("OPT DO should be %t, but is %t", tt.Do(), x.Do()) } } } - return true + return nil } // CNAMEOrder makes sure that CNAMES do not appear after their target records -func CNAMEOrder(t *testing.T, res *dns.Msg) { +func CNAMEOrder(res *dns.Msg) error { for i, c := range res.Answer { if c.Header().Rrtype != dns.TypeCNAME { continue @@ -284,38 +258,29 @@ func CNAMEOrder(t *testing.T, res *dns.Msg) { if a.Header().Name != c.(*dns.CNAME).Target { continue } - t.Errorf("CNAME found after target record\n") - t.Logf("%v\n", res) - + return fmt.Errorf("CNAME found after target record") } } + return nil } // SortAndCheck sorts resp and the checks the header and three sections against the testcase in tc. -func SortAndCheck(t *testing.T, resp *dns.Msg, tc Case) { +func SortAndCheck(resp *dns.Msg, tc Case) error { sort.Sort(RRSet(resp.Answer)) sort.Sort(RRSet(resp.Ns)) sort.Sort(RRSet(resp.Extra)) - if !Header(t, tc, resp) { - t.Logf("%v\n", resp) - return + if err := Header(tc, resp); err != nil { + return err } - - if !Section(t, tc, Answer, resp.Answer) { - t.Logf("%v\n", resp) - return + if err := Section(tc, Answer, resp.Answer); err != nil { + return err } - if !Section(t, tc, Ns, resp.Ns) { - t.Logf("%v\n", resp) - return + if err := Section(tc, Ns, resp.Ns); err != nil { + return err } - if !Section(t, tc, Extra, resp.Extra) { - t.Logf("%v\n", resp) - return - } - return + return Section(tc, Extra, resp.Extra) } // ErrorHandler returns a Handler that returns ServerFailure error when called. diff --git a/vendor/github.com/coredns/coredns/plugin/test/scrape.go b/vendor/github.com/coredns/coredns/plugin/test/scrape.go new file mode 100644 index 000000000..132a4f944 --- /dev/null +++ b/vendor/github.com/coredns/coredns/plugin/test/scrape.go @@ -0,0 +1,266 @@ +// Adapted by Miek Gieben for CoreDNS testing. +// +// License from prom2json +// Copyright 2014 Prometheus Team +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Package test will scrape a target and you can inspect the variables. +// Basic usage: +// +// result := Scrape("http://localhost:9153/metrics") +// v := MetricValue("coredns_cache_capacity", result) +// +package test + +import ( + "fmt" + "io" + "mime" + "net/http" + "strconv" + + "github.com/matttproud/golang_protobuf_extensions/pbutil" + "github.com/prometheus/common/expfmt" + + dto "github.com/prometheus/client_model/go" +) + +type ( + // MetricFamily holds a prometheus metric. + MetricFamily struct { + Name string `json:"name"` + Help string `json:"help"` + Type string `json:"type"` + Metrics []interface{} `json:"metrics,omitempty"` // Either metric or summary. + } + + // metric is for all "single value" metrics. + metric struct { + Labels map[string]string `json:"labels,omitempty"` + Value string `json:"value"` + } + + summary struct { + Labels map[string]string `json:"labels,omitempty"` + Quantiles map[string]string `json:"quantiles,omitempty"` + Count string `json:"count"` + Sum string `json:"sum"` + } + + histogram struct { + Labels map[string]string `json:"labels,omitempty"` + Buckets map[string]string `json:"buckets,omitempty"` + Count string `json:"count"` + Sum string `json:"sum"` + } +) + +// Scrape returns the all the vars a []*metricFamily. +func Scrape(url string) []*MetricFamily { + mfChan := make(chan *dto.MetricFamily, 1024) + + go fetchMetricFamilies(url, mfChan) + + result := []*MetricFamily{} + for mf := range mfChan { + result = append(result, newMetricFamily(mf)) + } + return result +} + +// ScrapeMetricAsInt provide a sum of all metrics collected for the name and label provided. +// if the metric is not a numeric value, it will be counted a 0. +func ScrapeMetricAsInt(addr string, name string, label string, nometricvalue int) int { + + valueToInt := func(m metric) int { + v := m.Value + r, err := strconv.Atoi(v) + if err != nil { + return 0 + } + return r + } + + met := Scrape(fmt.Sprintf("http://%s/metrics", addr)) + found := false + tot := 0 + for _, mf := range met { + if mf.Name == name { + // Sum all metrics available + for _, m := range mf.Metrics { + if label == "" { + tot += valueToInt(m.(metric)) + found = true + continue + } + for _, v := range m.(metric).Labels { + if v == label { + tot += valueToInt(m.(metric)) + found = true + } + } + } + } + } + + if !found { + return nometricvalue + } + return tot +} + +// MetricValue returns the value associated with name as a string as well as the labels. +// It only returns the first metrics of the slice. +func MetricValue(name string, mfs []*MetricFamily) (string, map[string]string) { + for _, mf := range mfs { + if mf.Name == name { + // Only works with Gauge and Counter... + return mf.Metrics[0].(metric).Value, mf.Metrics[0].(metric).Labels + } + } + return "", nil +} + +// MetricValueLabel returns the value for name *and* label *value*. +func MetricValueLabel(name, label string, mfs []*MetricFamily) (string, map[string]string) { + // bit hacky is this really handy...? + for _, mf := range mfs { + if mf.Name == name { + for _, m := range mf.Metrics { + for _, v := range m.(metric).Labels { + if v == label { + return m.(metric).Value, m.(metric).Labels + } + } + + } + } + } + return "", nil +} + +func newMetricFamily(dtoMF *dto.MetricFamily) *MetricFamily { + mf := &MetricFamily{ + Name: dtoMF.GetName(), + Help: dtoMF.GetHelp(), + Type: dtoMF.GetType().String(), + Metrics: make([]interface{}, len(dtoMF.Metric)), + } + for i, m := range dtoMF.Metric { + if dtoMF.GetType() == dto.MetricType_SUMMARY { + mf.Metrics[i] = summary{ + Labels: makeLabels(m), + Quantiles: makeQuantiles(m), + Count: fmt.Sprint(m.GetSummary().GetSampleCount()), + Sum: fmt.Sprint(m.GetSummary().GetSampleSum()), + } + } else if dtoMF.GetType() == dto.MetricType_HISTOGRAM { + mf.Metrics[i] = histogram{ + Labels: makeLabels(m), + Buckets: makeBuckets(m), + Count: fmt.Sprint(m.GetHistogram().GetSampleCount()), + Sum: fmt.Sprint(m.GetSummary().GetSampleSum()), + } + } else { + mf.Metrics[i] = metric{ + Labels: makeLabels(m), + Value: fmt.Sprint(value(m)), + } + } + } + return mf +} + +func value(m *dto.Metric) float64 { + if m.Gauge != nil { + return m.GetGauge().GetValue() + } + if m.Counter != nil { + return m.GetCounter().GetValue() + } + if m.Untyped != nil { + return m.GetUntyped().GetValue() + } + return 0. +} + +func makeLabels(m *dto.Metric) map[string]string { + result := map[string]string{} + for _, lp := range m.Label { + result[lp.GetName()] = lp.GetValue() + } + return result +} + +func makeQuantiles(m *dto.Metric) map[string]string { + result := map[string]string{} + for _, q := range m.GetSummary().Quantile { + result[fmt.Sprint(q.GetQuantile())] = fmt.Sprint(q.GetValue()) + } + return result +} + +func makeBuckets(m *dto.Metric) map[string]string { + result := map[string]string{} + for _, b := range m.GetHistogram().Bucket { + result[fmt.Sprint(b.GetUpperBound())] = fmt.Sprint(b.GetCumulativeCount()) + } + return result +} + +func fetchMetricFamilies(url string, ch chan<- *dto.MetricFamily) { + defer close(ch) + req, err := http.NewRequest("GET", url, nil) + if err != nil { + return + } + req.Header.Add("Accept", acceptHeader) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return + } + defer resp.Body.Close() + if resp.StatusCode != http.StatusOK { + return + } + + mediatype, params, err := mime.ParseMediaType(resp.Header.Get("Content-Type")) + if err == nil && mediatype == "application/vnd.google.protobuf" && + params["encoding"] == "delimited" && + params["proto"] == "io.prometheus.client.MetricFamily" { + for { + mf := &dto.MetricFamily{} + if _, err = pbutil.ReadDelimited(resp.Body, mf); err != nil { + if err == io.EOF { + break + } + return + } + ch <- mf + } + } else { + // We could do further content-type checks here, but the + // fallback for now will anyway be the text format + // version 0.0.4, so just go for it and see if it works. + var parser expfmt.TextParser + metricFamilies, err := parser.TextToMetricFamilies(resp.Body) + if err != nil { + return + } + for _, mf := range metricFamilies { + ch <- mf + } + } +} + +const acceptHeader = `application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.7,text/plain;version=0.0.4;q=0.3` diff --git a/vendor/github.com/coredns/coredns/request/edns0.go b/vendor/github.com/coredns/coredns/request/edns0.go new file mode 100644 index 000000000..89eb6b468 --- /dev/null +++ b/vendor/github.com/coredns/coredns/request/edns0.go @@ -0,0 +1,31 @@ +package request + +import ( + "github.com/coredns/coredns/plugin/pkg/edns" + + "github.com/miekg/dns" +) + +func supportedOptions(o []dns.EDNS0) []dns.EDNS0 { + var supported = make([]dns.EDNS0, 0, 3) + // For as long as possible try avoid looking up in the map, because that need an Rlock. + for _, opt := range o { + switch code := opt.Option(); code { + case dns.EDNS0NSID: + fallthrough + case dns.EDNS0EXPIRE: + fallthrough + case dns.EDNS0COOKIE: + fallthrough + case dns.EDNS0TCPKEEPALIVE: + fallthrough + case dns.EDNS0PADDING: + supported = append(supported, opt) + default: + if edns.SupportedOption(code) { + supported = append(supported, opt) + } + } + } + return supported +} diff --git a/vendor/github.com/coredns/coredns/request/request.go b/vendor/github.com/coredns/coredns/request/request.go index 260d73f5e..0ec98b310 100644 --- a/vendor/github.com/coredns/coredns/request/request.go +++ b/vendor/github.com/coredns/coredns/request/request.go @@ -2,7 +2,6 @@ package request import ( - "context" "net" "strings" @@ -19,12 +18,9 @@ type Request struct { // Optional lowercased zone of this query. Zone string - Context context.Context - // Cache size after first call to Size or Do. size int do *bool // nil: nothing, otherwise *do value - // TODO(miek): opt record itself as well? // Caches name string // lowercase qname. @@ -192,15 +188,13 @@ func (r *Request) Size() int { } // SizeAndDo adds an OPT record that the reflects the intent from request. -// The returned bool indicated if an record was found and normalised. +// The returned bool indicates if an record was found and normalised. func (r *Request) SizeAndDo(m *dns.Msg) bool { - o := r.Req.IsEdns0() // TODO(miek): speed this up + o := r.Req.IsEdns0() if o == nil { return false } - odo := o.Do() - if mo := m.IsEdns0(); mo != nil { mo.Hdr.Name = "." mo.Hdr.Rrtype = dns.TypeOPT @@ -208,20 +202,24 @@ func (r *Request) SizeAndDo(m *dns.Msg) bool { mo.SetUDPSize(o.UDPSize()) mo.Hdr.Ttl &= 0xff00 // clear flags - if odo { + // Assume if the message m has options set, they are OK and represent what an upstream can do. + + if o.Do() { mo.SetDo() } return true } + // Reuse the request's OPT record and tack it to m. o.Hdr.Name = "." o.Hdr.Rrtype = dns.TypeOPT o.SetVersion(0) o.Hdr.Ttl &= 0xff00 // clear flags - if odo { - o.SetDo() + if len(o.Option) > 0 { + o.Option = supportedOptions(o.Option) } + m.Extra = append(m.Extra, o) return true } @@ -240,6 +238,23 @@ func (r *Request) Scrub(reply *dns.Msg) *dns.Msg { reply.Compress = false rl := reply.Len() if size >= rl { + if r.Proto() != "udp" { + return reply + } + + // Last ditch attempt to avoid fragmentation, if the size is bigger than the v4/v6 UDP fragmentation + // limit and sent via UDP compress it (in the hope we go under that limit). Limits taken from NSD: + // + // .., 1480 (EDNS/IPv4), 1220 (EDNS/IPv6), or the advertized EDNS buffer size if that is + // smaller than the EDNS default. + // See: https://open.nlnetlabs.nl/pipermail/nsd-users/2011-November/001278.html + if rl > 1480 && r.Family() == 1 { + reply.Compress = true + } + if rl > 1220 && r.Family() == 2 { + reply.Compress = true + } + return reply } @@ -280,15 +295,14 @@ func (r *Request) Scrub(reply *dns.Msg) *dns.Msg { // pretty rare. Normally, the loop will exit when l > re, meaning that // in the previous iteration either: // rl < size: no need to do anything. - // rl > size: the final size is too large, and if m > 0, the preceeding - // iteration the size was too small. Select that preceeding size. + // rl > size: the final size is too large, and if m > 0, the preceding + // iteration the size was too small. Select that preceding size. if rl > size && m > 0 { reply.Extra = origExtra[:m-1] rl = reply.Len() } if rl <= size { - r.SizeAndDo(reply) return reply } @@ -316,15 +330,14 @@ func (r *Request) Scrub(reply *dns.Msg) *dns.Msg { // pretty rare. Normally, the loop will exit when l > ra, meaning that // in the previous iteration either: // rl < size: no need to do anything. - // rl > size: the final size is too large, and if m > 0, the preceeding - // iteration the size was too small. Select that preceeding size. + // rl > size: the final size is too large, and if m > 0, the preceding + // iteration the size was too small. Select that preceding size. if rl > size && m > 0 { reply.Answer = origAnswer[:m-1] // No need to recalc length, as we don't use it. We set truncated anyway. Doing // this extra m-1 step does make it fit in the client's buffer however. } - r.SizeAndDo(reply) reply.Truncated = true return reply } @@ -416,14 +429,6 @@ func (r *Request) QClass() uint16 { } -// ErrorMessage returns an error message suitable for sending -// back to the client. -func (r *Request) ErrorMessage(rcode int) *dns.Msg { - m := new(dns.Msg) - m.SetRcode(r.Req, rcode) - return m -} - // Clear clears all caching from Request s. func (r *Request) Clear() { r.name = "" diff --git a/vendor/github.com/coredns/coredns/request/writer.go b/vendor/github.com/coredns/coredns/request/writer.go index ffbbe93e3..6caba0c2e 100644 --- a/vendor/github.com/coredns/coredns/request/writer.go +++ b/vendor/github.com/coredns/coredns/request/writer.go @@ -11,10 +11,12 @@ type ScrubWriter struct { // NewScrubWriter returns a new and initialized ScrubWriter. func NewScrubWriter(req *dns.Msg, w dns.ResponseWriter) *ScrubWriter { return &ScrubWriter{w, req} } -// WriteMsg overrides the default implementation of the underlaying dns.ResponseWriter and calls +// WriteMsg overrides the default implementation of the underlying dns.ResponseWriter and calls // scrub on the message m and will then write it to the client. func (s *ScrubWriter) WriteMsg(m *dns.Msg) error { state := Request{Req: s.req, W: s.ResponseWriter} + n := state.Scrub(m) + state.SizeAndDo(n) return s.ResponseWriter.WriteMsg(n) }