diff options
Diffstat (limited to 'middleware/erratic')
-rw-r--r-- | middleware/erratic/README.md | 76 | ||||
-rw-r--r-- | middleware/erratic/autopath.go | 8 | ||||
-rw-r--r-- | middleware/erratic/erratic.go | 95 | ||||
-rw-r--r-- | middleware/erratic/erratic_test.go | 79 | ||||
-rw-r--r-- | middleware/erratic/setup.go | 117 | ||||
-rw-r--r-- | middleware/erratic/setup_test.go | 103 |
6 files changed, 0 insertions, 478 deletions
diff --git a/middleware/erratic/README.md b/middleware/erratic/README.md deleted file mode 100644 index a84146fbb..000000000 --- a/middleware/erratic/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# erratic - -*erratic* is a middleware useful for testing client behavior. It returns a static response to all -queries, but the responses can be delayed, dropped or truncated. - -The *erratic* middleware will respond to every A or AAAA query. For any other type it will return -a SERVFAIL response. The reply for A will return 192.0.2.53 (see RFC 5737), for AAAA it returns -2001:DB8::53 (see RFC 3849). - -*erratic* can also be used in conjunction with the *autopath* middleware. This is mostly to aid in - testing. - -## Syntax - -~~~ txt -erratic { - drop [AMOUNT] - truncate [AMOUNT] - delay [AMOUNT [DURATION]] -} -~~~ - -* `drop`: drop 1 per **AMOUNT** of queries, the default is 2. -* `truncate`: truncate 1 per **AMOUNT** of queries, the default is 2. -* `delay`: delay 1 per **AMOUNT** of queries for **DURATION**, the default for **AMOUNT** is 2 and - the default for **DURATION** is 100ms. - -## Examples - -~~~ txt -.:53 { - erratic { - drop 3 - } -} -~~~ - -Or even shorter if the defaults suits you. Note this only drops queries, it does not delay them. - -~~~ txt -. { - erratic -} -~~~ - -Delay 1 in 3 queries for 50ms - -~~~ txt -. { - erratic { - delay 3 50ms - } -} -~~~ - -Delay 1 in 3 and truncate 1 in 5. - -~~~ txt -. { - erratic { - delay 3 5ms - truncate 5 - } -} -~~~ - -Drop every second query. - -~~~ txt -. { - erratic { - drop 2 - truncate 2 - } -} -~~~ diff --git a/middleware/erratic/autopath.go b/middleware/erratic/autopath.go deleted file mode 100644 index 79b0ec847..000000000 --- a/middleware/erratic/autopath.go +++ /dev/null @@ -1,8 +0,0 @@ -package erratic - -import "github.com/coredns/coredns/request" - -// AutoPath implements the AutoPathFunc call from the autopath middleware. -func (e *Erratic) AutoPath(state request.Request) []string { - return []string{"a.example.org.", "b.example.org.", ""} -} diff --git a/middleware/erratic/erratic.go b/middleware/erratic/erratic.go deleted file mode 100644 index b05e45f03..000000000 --- a/middleware/erratic/erratic.go +++ /dev/null @@ -1,95 +0,0 @@ -// Package erratic implements a middleware that returns erratic answers (delayed, dropped). -package erratic - -import ( - "sync/atomic" - "time" - - "github.com/coredns/coredns/request" - - "github.com/miekg/dns" - "golang.org/x/net/context" -) - -// Erratic is a middleware that returns erratic repsonses to each client. -type Erratic struct { - drop uint64 - - delay uint64 - duration time.Duration - - truncate uint64 - - q uint64 // counter of queries -} - -// ServeDNS implements the middleware.Handler interface. -func (e *Erratic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { - state := request.Request{W: w, Req: r} - drop := false - delay := false - trunc := false - - queryNr := atomic.LoadUint64(&e.q) - atomic.AddUint64(&e.q, 1) - - if e.drop > 0 && queryNr%e.drop == 0 { - drop = true - } - if e.delay > 0 && queryNr%e.delay == 0 { - delay = true - } - if e.truncate > 0 && queryNr&e.truncate == 0 { - trunc = true - } - - m := new(dns.Msg) - m.SetReply(r) - m.Compress = true - m.Authoritative = true - if trunc { - m.Truncated = true - } - - // small dance to copy rrA or rrAAAA into a non-pointer var that allows us to overwrite the ownername - // in a non-racy way. - switch state.QType() { - case dns.TypeA: - rr := *(rrA.(*dns.A)) - rr.Header().Name = state.QName() - m.Answer = append(m.Answer, &rr) - case dns.TypeAAAA: - rr := *(rrAAAA.(*dns.AAAA)) - rr.Header().Name = state.QName() - m.Answer = append(m.Answer, &rr) - default: - if !drop { - if delay { - time.Sleep(e.duration) - } - // coredns will return error. - return dns.RcodeServerFailure, nil - } - } - - if drop { - return 0, nil - } - - if delay { - time.Sleep(e.duration) - } - - state.SizeAndDo(m) - w.WriteMsg(m) - - return 0, nil -} - -// Name implements the Handler interface. -func (e *Erratic) Name() string { return "erratic" } - -var ( - rrA, _ = dns.NewRR(". IN 0 A 192.0.2.53") - rrAAAA, _ = dns.NewRR(". IN 0 AAAA 2001:DB8::53") -) diff --git a/middleware/erratic/erratic_test.go b/middleware/erratic/erratic_test.go deleted file mode 100644 index 4b54e0c12..000000000 --- a/middleware/erratic/erratic_test.go +++ /dev/null @@ -1,79 +0,0 @@ -package erratic - -import ( - "testing" - - "github.com/coredns/coredns/middleware/pkg/dnsrecorder" - "github.com/coredns/coredns/middleware/test" - - "github.com/miekg/dns" - "golang.org/x/net/context" -) - -func TestErraticDrop(t *testing.T) { - e := &Erratic{drop: 2} // 50% drops - - tests := []struct { - expectedCode int - expectedErr error - drop bool - }{ - {expectedCode: dns.RcodeSuccess, expectedErr: nil, drop: true}, - {expectedCode: dns.RcodeSuccess, expectedErr: nil, drop: false}, - } - - ctx := context.TODO() - - for i, tc := range tests { - req := new(dns.Msg) - req.SetQuestion("example.org.", dns.TypeA) - - rec := dnsrecorder.New(&test.ResponseWriter{}) - code, err := e.ServeDNS(ctx, rec, req) - - if err != tc.expectedErr { - t.Errorf("Test %d: Expected error %q, but got %q", i, tc.expectedErr, err) - } - if code != int(tc.expectedCode) { - t.Errorf("Test %d: Expected status code %d, but got %d", i, tc.expectedCode, code) - } - - if tc.drop && rec.Msg != nil { - t.Errorf("Test %d: Expected dropped message, but got %q", i, rec.Msg.Question[0].Name) - } - } -} - -func TestErraticTruncate(t *testing.T) { - e := &Erratic{truncate: 2} // 50% drops - - tests := []struct { - expectedCode int - expectedErr error - truncate bool - }{ - {expectedCode: dns.RcodeSuccess, expectedErr: nil, truncate: true}, - {expectedCode: dns.RcodeSuccess, expectedErr: nil, truncate: false}, - } - - ctx := context.TODO() - - for i, tc := range tests { - req := new(dns.Msg) - req.SetQuestion("example.org.", dns.TypeA) - - rec := dnsrecorder.New(&test.ResponseWriter{}) - code, err := e.ServeDNS(ctx, rec, req) - - if err != tc.expectedErr { - t.Errorf("Test %d: Expected error %q, but got %q", i, tc.expectedErr, err) - } - if code != int(tc.expectedCode) { - t.Errorf("Test %d: Expected status code %d, but got %d", i, tc.expectedCode, code) - } - - if tc.truncate && !rec.Msg.Truncated { - t.Errorf("Test %d: Expected truncated message, but got %q", i, rec.Msg.Question[0].Name) - } - } -} diff --git a/middleware/erratic/setup.go b/middleware/erratic/setup.go deleted file mode 100644 index 98db02247..000000000 --- a/middleware/erratic/setup.go +++ /dev/null @@ -1,117 +0,0 @@ -package erratic - -import ( - "fmt" - "strconv" - "time" - - "github.com/coredns/coredns/core/dnsserver" - "github.com/coredns/coredns/middleware" - - "github.com/mholt/caddy" -) - -func init() { - caddy.RegisterPlugin("erratic", caddy.Plugin{ - ServerType: "dns", - Action: setupErratic, - }) -} - -func setupErratic(c *caddy.Controller) error { - e, err := parseErratic(c) - if err != nil { - return middleware.Error("erratic", err) - } - - dnsserver.GetConfig(c).AddMiddleware(func(next middleware.Handler) middleware.Handler { - return e - }) - - return nil -} - -func parseErratic(c *caddy.Controller) (*Erratic, error) { - e := &Erratic{drop: 2} - drop := false // true if we've seen the drop keyword - - for c.Next() { // 'erratic' - for c.NextBlock() { - switch c.Val() { - case "drop": - args := c.RemainingArgs() - if len(args) > 1 { - return nil, c.ArgErr() - } - - if len(args) == 0 { - continue - } - - amount, err := strconv.ParseInt(args[0], 10, 32) - if err != nil { - return nil, err - } - if amount < 0 { - return nil, fmt.Errorf("illegal amount value given %q", args[0]) - } - e.drop = uint64(amount) - drop = true - case "delay": - args := c.RemainingArgs() - if len(args) > 2 { - return nil, c.ArgErr() - } - - // Defaults. - e.delay = 2 - e.duration = 100 * time.Millisecond - if len(args) == 0 { - continue - } - - amount, err := strconv.ParseInt(args[0], 10, 32) - if err != nil { - return nil, err - } - if amount < 0 { - return nil, fmt.Errorf("illegal amount value given %q", args[0]) - } - e.delay = uint64(amount) - - if len(args) > 1 { - duration, err := time.ParseDuration(args[1]) - if err != nil { - return nil, err - } - e.duration = duration - } - case "truncate": - args := c.RemainingArgs() - if len(args) > 1 { - return nil, c.ArgErr() - } - - if len(args) == 0 { - continue - } - - amount, err := strconv.ParseInt(args[0], 10, 32) - if err != nil { - return nil, err - } - if amount < 0 { - return nil, fmt.Errorf("illegal amount value given %q", args[0]) - } - e.truncate = uint64(amount) - default: - return nil, c.Errf("unknown property '%s'", c.Val()) - } - } - } - if (e.delay > 0 || e.truncate > 0) && !drop { // delay is set, but we've haven't seen a drop keyword, remove default drop stuff - e.drop = 0 - } - - return e, nil -} diff --git a/middleware/erratic/setup_test.go b/middleware/erratic/setup_test.go deleted file mode 100644 index 759845f7a..000000000 --- a/middleware/erratic/setup_test.go +++ /dev/null @@ -1,103 +0,0 @@ -package erratic - -import ( - "testing" - - "github.com/mholt/caddy" -) - -func TestSetupErratic(t *testing.T) { - c := caddy.NewTestController("dns", `erratic { - drop - }`) - if err := setupErratic(c); err != nil { - t.Fatalf("Test 1, expected no errors, but got: %q", err) - } - - c = caddy.NewTestController("dns", `erratic`) - if err := setupErratic(c); err != nil { - t.Fatalf("Test 2, expected no errors, but got: %q", err) - } - - c = caddy.NewTestController("dns", `erratic { - drop -1 - }`) - if err := setupErratic(c); err == nil { - t.Fatalf("Test 4, expected errors, but got: %q", err) - } -} - -func TestParseErratic(t *testing.T) { - tests := []struct { - input string - shouldErr bool - drop uint64 - delay uint64 - truncate uint64 - }{ - // oks - {`erratic`, false, 2, 0, 0}, - {`erratic { - drop 2 - delay 3 1ms - - }`, false, 2, 3, 0}, - {`erratic { - truncate 2 - delay 3 1ms - - }`, false, 0, 3, 2}, - {`erraric { - drop 3 - delay - }`, false, 3, 2, 0}, - // fails - {`erratic { - drop -1 - }`, true, 0, 0, 0}, - {`erratic { - delay -1 - }`, true, 0, 0, 0}, - {`erratic { - delay 1 2 4 - }`, true, 0, 0, 0}, - {`erratic { - delay 15.a - }`, true, 0, 0, 0}, - {`erraric { - drop 3 - delay 3 bla - }`, true, 0, 0, 0}, - {`erraric { - truncate 15.a - }`, true, 0, 0, 0}, - {`erraric { - something-else - }`, true, 0, 0, 0}, - } - for i, test := range tests { - c := caddy.NewTestController("dns", test.input) - e, err := parseErratic(c) - if test.shouldErr && err == nil { - t.Errorf("Test %v: Expected error but found nil", i) - continue - } else if !test.shouldErr && err != nil { - t.Errorf("Test %v: Expected no error but found error: %v", i, err) - continue - } - - if test.shouldErr { - continue - } - - if test.delay != e.delay { - t.Errorf("Test %v: Expected delay %d but found: %d", i, test.delay, e.delay) - } - if test.drop != e.drop { - t.Errorf("Test %v: Expected drop %d but found: %d", i, test.drop, e.drop) - } - if test.truncate != e.truncate { - t.Errorf("Test %v: Expected truncate %d but found: %d", i, test.truncate, e.truncate) - } - } -} |