aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Miek Gieben <miek@miek.nl> 2017-06-13 15:47:17 -0700
committerGravatar Pat Moroney <pat@moroney.email> 2017-06-13 16:47:17 -0600
commit8e86fa6f2375136d746c9d85f492a1d0b813d687 (patch)
treecdc7db86c9a83964bd1f4aa77a29bab654161daa
parent46bf7f31069137aee8a82bc4f8287ce60117652c (diff)
downloadcoredns-8e86fa6f2375136d746c9d85f492a1d0b813d687.tar.gz
coredns-8e86fa6f2375136d746c9d85f492a1d0b813d687.tar.zst
coredns-8e86fa6f2375136d746c9d85f492a1d0b813d687.zip
middleware/debug: add (#735)
* middleware/debug: add Add a debug "middleware" that disables the recover() and just lets CoreDNS crash; very useful for testing. Fixes ##563 * fix test * Feedback: check the value of Debug
-rw-r--r--core/dnsserver/config.go3
-rw-r--r--core/dnsserver/server.go20
-rw-r--r--core/dnsserver/zdirectives.go1
-rw-r--r--core/zmiddleware.go1
-rw-r--r--middleware.cfg43
-rw-r--r--middleware/debug/README.md20
-rw-r--r--middleware/debug/debug.go28
-rw-r--r--middleware/debug/debug_test.go49
8 files changed, 137 insertions, 28 deletions
diff --git a/core/dnsserver/config.go b/core/dnsserver/config.go
index 942d43d58..c0f879a31 100644
--- a/core/dnsserver/config.go
+++ b/core/dnsserver/config.go
@@ -23,6 +23,9 @@ type Config struct {
// First consumer is the file middleware to looks for zone files in this place.
Root string
+ // Debug controls the panic/recover mechanism that is enabled by default.
+ Debug bool
+
// The transport we implement, normally just "dns" over TCP/UDP, but could be
// DNS-over-TLS or DNS-over-gRPC.
Transport string
diff --git a/core/dnsserver/server.go b/core/dnsserver/server.go
index 5bbbf9f9c..61ef6ac65 100644
--- a/core/dnsserver/server.go
+++ b/core/dnsserver/server.go
@@ -36,6 +36,7 @@ type Server struct {
dnsWg sync.WaitGroup // used to wait on outstanding connections
connTimeout time.Duration // the maximum duration of a graceful shutdown
trace trace.Trace // the trace middleware for the server
+ debug bool // disable recover()
}
// NewServer returns a new CoreDNS server and compiles all middleware in to it.
@@ -56,6 +57,9 @@ func NewServer(addr string, group []*Config) (*Server, error) {
s.dnsWg.Add(1)
for _, site := range group {
+ if site.Debug {
+ s.debug = true
+ }
// set the config per zone
s.zones[site.Zone] = site
// compile custom middleware for everything
@@ -166,13 +170,15 @@ func (s *Server) Address() string { return s.Addr }
// defined in the request so that the correct zone
// (configuration and middleware stack) will handle the request.
func (s *Server) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) {
- defer func() {
- // In case the user doesn't enable error middleware, we still
- // need to make sure that we stay alive up here
- if rec := recover(); rec != nil {
- DefaultErrorFunc(w, r, dns.RcodeServerFailure)
- }
- }()
+ if !s.debug {
+ defer func() {
+ // In case the user doesn't enable error middleware, we still
+ // need to make sure that we stay alive up here
+ if rec := recover(); rec != nil {
+ DefaultErrorFunc(w, r, dns.RcodeServerFailure)
+ }
+ }()
+ }
if m, err := edns.Version(r); err != nil { // Wrong EDNS version, return at once.
w.WriteMsg(m)
diff --git a/core/dnsserver/zdirectives.go b/core/dnsserver/zdirectives.go
index a794ce762..1af5d3c7e 100644
--- a/core/dnsserver/zdirectives.go
+++ b/core/dnsserver/zdirectives.go
@@ -14,6 +14,7 @@ var directives = []string{
"tls",
"root",
"bind",
+ "debug",
"trace",
"health",
"pprof",
diff --git a/core/zmiddleware.go b/core/zmiddleware.go
index cd611333e..0496dcd0e 100644
--- a/core/zmiddleware.go
+++ b/core/zmiddleware.go
@@ -8,6 +8,7 @@ import (
_ "github.com/coredns/coredns/middleware/bind"
_ "github.com/coredns/coredns/middleware/cache"
_ "github.com/coredns/coredns/middleware/chaos"
+ _ "github.com/coredns/coredns/middleware/debug"
_ "github.com/coredns/coredns/middleware/dnssec"
_ "github.com/coredns/coredns/middleware/erratic"
_ "github.com/coredns/coredns/middleware/errors"
diff --git a/middleware.cfg b/middleware.cfg
index 562557b73..00e6eba6c 100644
--- a/middleware.cfg
+++ b/middleware.cfg
@@ -22,26 +22,27 @@
1:tls:tls
10:root:root
20:bind:bind
-30:trace:trace
-40:health:health
-50:pprof:pprof
-60:prometheus:metrics
-70:errors:errors
-80:log:log
-90:chaos:chaos
-100:cache:cache
-110:rewrite:rewrite
-120:loadbalance:loadbalance
-130:dnssec:dnssec
-140:reverse:reverse
-150:hosts:hosts
-160:kubernetes:kubernetes
-170:file:file
-180:auto:auto
-190:secondary:secondary
-200:etcd:etcd
-210:proxy:proxy
-220:whoami:whoami
-230:erratic:erratic
+30:debug:debug
+40:trace:trace
+50:health:health
+60:pprof:pprof
+70:prometheus:metrics
+80:errors:errors
+90:log:log
+100:chaos:chaos
+110:cache:cache
+120:rewrite:rewrite
+130:loadbalance:loadbalance
+140:dnssec:dnssec
+150:reverse:reverse
+160:hosts:hosts
+170:kubernetes:kubernetes
+180:file:file
+190:auto:auto
+200:secondary:secondary
+210:etcd:etcd
+220:proxy:proxy
+230:whoami:whoami
+240:erratic:erratic
500:startup:github.com/mholt/caddy/startupshutdown
510:shutdown:github.com/mholt/caddy/startupshutdown
diff --git a/middleware/debug/README.md b/middleware/debug/README.md
new file mode 100644
index 000000000..b74d95612
--- /dev/null
+++ b/middleware/debug/README.md
@@ -0,0 +1,20 @@
+# debug
+
+*debug* disables the automatic recovery upon a CoreDNS crash so that you'll get a
+nice stack trace.
+Note that the *errors* middleware (if loaded) will also set a `recover` negating this setting.
+The main use of *debug* is to help testing.
+
+## Syntax
+
+~~~ txt
+debug
+~~~
+
+## Examples
+
+Disable CoreDNS' ability to recover from crashes:
+
+~~~ txt
+debug
+~~~
diff --git a/middleware/debug/debug.go b/middleware/debug/debug.go
new file mode 100644
index 000000000..f92a27554
--- /dev/null
+++ b/middleware/debug/debug.go
@@ -0,0 +1,28 @@
+package debug
+
+import (
+ "github.com/coredns/coredns/core/dnsserver"
+ "github.com/coredns/coredns/middleware"
+
+ "github.com/mholt/caddy"
+)
+
+func init() {
+ caddy.RegisterPlugin("debug", caddy.Plugin{
+ ServerType: "dns",
+ Action: setup,
+ })
+}
+
+func setup(c *caddy.Controller) error {
+ config := dnsserver.GetConfig(c)
+
+ for c.Next() {
+ if c.NextArg() {
+ return middleware.Error("debug", c.ArgErr())
+ }
+ config.Debug = true
+ }
+
+ return nil
+}
diff --git a/middleware/debug/debug_test.go b/middleware/debug/debug_test.go
new file mode 100644
index 000000000..349b362f1
--- /dev/null
+++ b/middleware/debug/debug_test.go
@@ -0,0 +1,49 @@
+package debug
+
+import (
+ "io/ioutil"
+ "log"
+ "testing"
+
+ "github.com/coredns/coredns/core/dnsserver"
+
+ "github.com/mholt/caddy"
+)
+
+func TestDebug(t *testing.T) {
+ log.SetOutput(ioutil.Discard)
+
+ tests := []struct {
+ input string
+ shouldErr bool
+ expectedDebug bool
+ }{
+ // positive
+ {
+ `debug`, false, true,
+ },
+ // negative
+ {
+ `debug off`, true, false,
+ },
+ }
+
+ for i, test := range tests {
+ c := caddy.NewTestController("dns", test.input)
+ err := setup(c)
+ cfg := dnsserver.GetConfig(c)
+
+ if test.shouldErr && err == nil {
+ t.Fatalf("Test %d: Expected error but found %s for input %s", i, err, test.input)
+ }
+
+ if err != nil {
+ if !test.shouldErr {
+ t.Fatalf("Test %d: Expected no error but found one for input %s. Error was: %v", i, test.input, err)
+ }
+ }
+ if cfg.Debug != test.expectedDebug {
+ t.Fatalf("Test %d: Expected debug to be: %t, but got: %t, input: %s", i, test.expectedDebug, test.input)
+ }
+ }
+}