Add cache_capacity option to dnssec middleware for the capacity of LRU cache (#339)

This fix adds a `cache_capacity` option to dnssec middleware, so that
it is possible to specify the capacity of the LRU cache used by dnssec
middleware.

Signed-off-by: Yong Tang <yong.tang.github@outlook.com>
This commit is contained in:
Yong Tang 2016-10-18 13:33:23 -07:00 committed by GitHub
parent 4d55f90388
commit ad7e78ec31
3 changed files with 58 additions and 30 deletions

View file

@ -26,6 +26,7 @@ TODO(miek): think about key rollovers, and how to do them automatically.
~~~ ~~~
dnssec [ZONES... ] { dnssec [ZONES... ] {
key file KEY... key file KEY...
cache_capacity CAPACITY
} }
~~~ ~~~
@ -33,4 +34,9 @@ dnssec [ZONES... ] {
will be signed with all keys. Generating a key can be done with `dnssec-keygen`: `dnssec-keygen -a will be signed with all keys. Generating a key can be done with `dnssec-keygen`: `dnssec-keygen -a
ECDSAP256SHA256 <zonename>`. A key created for zone *A* can be safely used for zone *B*. ECDSAP256SHA256 <zonename>`. A key created for zone *A* can be safely used for zone *B*.
* `cache_capacity` indicates the capacity of the LRU cache. The dnssec middleware uses LRU cache to manage
objects and the default capacity is 10000.
## Examples ## Examples

View file

@ -1,6 +1,7 @@
package dnssec package dnssec
import ( import (
"strconv"
"strings" "strings"
"github.com/miekg/coredns/core/dnsserver" "github.com/miekg/coredns/core/dnsserver"
@ -18,12 +19,12 @@ func init() {
} }
func setup(c *caddy.Controller) error { func setup(c *caddy.Controller) error {
zones, keys, err := dnssecParse(c) zones, keys, capacity, err := dnssecParse(c)
if err != nil { if err != nil {
return middleware.Error("dnssec", err) return middleware.Error("dnssec", err)
} }
cache, err := lru.New(defaultCap) cache, err := lru.New(capacity)
if err != nil { if err != nil {
return err return err
} }
@ -34,10 +35,12 @@ func setup(c *caddy.Controller) error {
return nil return nil
} }
func dnssecParse(c *caddy.Controller) ([]string, []*DNSKEY, error) { func dnssecParse(c *caddy.Controller) ([]string, []*DNSKEY, int, error) {
zones := []string{} zones := []string{}
keys := []*DNSKEY{} keys := []*DNSKEY{}
capacity := defaultCap
for c.Next() { for c.Next() {
if c.Val() == "dnssec" { if c.Val() == "dnssec" {
// dnssec [zones...] // dnssec [zones...]
@ -49,30 +52,41 @@ func dnssecParse(c *caddy.Controller) ([]string, []*DNSKEY, error) {
} }
for c.NextBlock() { for c.NextBlock() {
switch c.Val() {
case "key":
k, e := keyParse(c) k, e := keyParse(c)
if e != nil { if e != nil {
return nil, nil, e return nil, nil, 0, e
} }
keys = append(keys, k...) keys = append(keys, k...)
case "cache_capacity":
if !c.NextArg() {
return nil, nil, 0, c.ArgErr()
}
value := c.Val()
cacheCap, err := strconv.Atoi(value)
if err != nil {
return nil, nil, 0, err
}
capacity = cacheCap
}
} }
} }
} }
for i := range zones { for i := range zones {
zones[i] = middleware.Host(zones[i]).Normalize() zones[i] = middleware.Host(zones[i]).Normalize()
} }
return zones, keys, nil return zones, keys, capacity, nil
} }
func keyParse(c *caddy.Controller) ([]*DNSKEY, error) { func keyParse(c *caddy.Controller) ([]*DNSKEY, error) {
keys := []*DNSKEY{} keys := []*DNSKEY{}
what := c.Val()
if !c.NextArg() { if !c.NextArg() {
return nil, c.ArgErr() return nil, c.ArgErr()
} }
value := c.Val() value := c.Val()
switch what {
case "key":
if value == "file" { if value == "file" {
ks := c.RemainingArgs() ks := c.RemainingArgs()
for _, k := range ks { for _, k := range ks {
@ -91,6 +105,5 @@ func keyParse(c *caddy.Controller) ([]*DNSKEY, error) {
keys = append(keys, k) keys = append(keys, k)
} }
} }
}
return keys, nil return keys, nil
} }

View file

@ -13,19 +13,25 @@ func TestSetupDnssec(t *testing.T) {
shouldErr bool shouldErr bool
expectedZones []string expectedZones []string
expectedKeys []string expectedKeys []string
expectedCapacity int
expectedErrContent string expectedErrContent string
}{ }{
{ {
`dnssec`, false, nil, nil, "", `dnssec`, false, nil, nil, defaultCap, "",
}, },
{ {
`dnssec miek.nl`, false, []string{"miek.nl."}, nil, "", `dnssec miek.nl`, false, []string{"miek.nl."}, nil, defaultCap, "",
},
{
`dnssec miek.nl {
cache_capacity 100
}`, false, []string{"miek.nl."}, nil, 100, "",
}, },
} }
for i, test := range tests { for i, test := range tests {
c := caddy.NewTestController("dns", test.input) c := caddy.NewTestController("dns", test.input)
zones, keys, err := dnssecParse(c) zones, keys, capacity, err := dnssecParse(c)
if test.shouldErr && err == nil { if test.shouldErr && err == nil {
t.Errorf("Test %d: Expected error but found %s for input %s", i, err, test.input) t.Errorf("Test %d: Expected error but found %s for input %s", i, err, test.input)
@ -51,6 +57,9 @@ func TestSetupDnssec(t *testing.T) {
t.Errorf("Dnssec not correctly set for input %s. Expected: '%s', actual: '%s'", test.input, k, keys[i].K.Header().Name) t.Errorf("Dnssec not correctly set for input %s. Expected: '%s', actual: '%s'", test.input, k, keys[i].K.Header().Name)
} }
} }
if capacity != test.expectedCapacity {
t.Errorf("Dnssec not correctly set capacity for input '%s' Expected: '%d', actual: '%d'", test.input, capacity, test.expectedCapacity)
}
} }
} }
} }