plugin/route53: add fallthrough (#2132)

Automatically submitted.
This commit is contained in:
Can Yucel
2018-09-25 11:41:05 -07:00
committed by corbot[bot]
parent b89006dda1
commit 8d4378d712
5 changed files with 65 additions and 2 deletions

View File

@@ -16,6 +16,7 @@ The route53 plugin can be used when coredns is deployed on AWS or elsewhere.
route53 [ZONE:HOSTED_ZONE_ID...] { route53 [ZONE:HOSTED_ZONE_ID...] {
[aws_access_key AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY] [aws_access_key AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY]
upstream [ADDRESS...] upstream [ADDRESS...]
fallthrough [ZONES...]
} }
~~~ ~~~
@@ -29,6 +30,12 @@ route53 [ZONE:HOSTED_ZONE_ID...] {
to external hosts (eg. used to resolve CNAMEs). If no **ADDRESS** is given, CoreDNS will resolve to external hosts (eg. used to resolve CNAMEs). If no **ADDRESS** is given, CoreDNS will resolve
against itself. **ADDRESS** can be an IP, an IP:port or a path to a file structured like against itself. **ADDRESS** can be an IP, an IP:port or a path to a file structured like
resolv.conf (**NB**: Currently a bug (#2099) is preventing the use of self-resolver). resolv.conf (**NB**: Currently a bug (#2099) is preventing the use of self-resolver).
are used.
* `fallthrough` If zone matches and no record can be generated, pass request to the next plugin.
If **[ZONES...]** is omitted, then fallthrough happens for all zones for which the plugin
is authoritative. If specific zones are listed (for example `in-addr.arpa` and `ip6.arpa`), then only
queries for those zones will be subject to fallthrough.
* **ZONES** zones it should be authoritative for. If empty, the zones from the configuration block
## Examples ## Examples
@@ -47,6 +54,16 @@ Enable route53 with explicit aws credentials:
. { . {
route53 example.org.:Z1Z2Z3Z4DZ5Z6Z7 { route53 example.org.:Z1Z2Z3Z4DZ5Z6Z7 {
aws_access_key AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY aws_access_key AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY
} }
}
~~~
Enable route53 with fallthrough:
~~~ txt
. {
route53 example.org.:Z1Z2Z3Z4DZ5Z6Z7 example.gov.:Z654321543245 {
fallthrough example.gov.
}
} }
~~~ ~~~

View File

@@ -10,6 +10,7 @@ import (
"github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin"
"github.com/coredns/coredns/plugin/file" "github.com/coredns/coredns/plugin/file"
"github.com/coredns/coredns/plugin/pkg/fall"
"github.com/coredns/coredns/plugin/pkg/upstream" "github.com/coredns/coredns/plugin/pkg/upstream"
"github.com/coredns/coredns/request" "github.com/coredns/coredns/request"
@@ -22,6 +23,7 @@ import (
// Route53 is a plugin that returns RR from AWS route53. // Route53 is a plugin that returns RR from AWS route53.
type Route53 struct { type Route53 struct {
Next plugin.Handler Next plugin.Handler
Fall fall.F
zoneNames []string zoneNames []string
client route53iface.Route53API client route53iface.Route53API
@@ -103,6 +105,10 @@ func (h *Route53) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg
m.Answer, m.Ns, m.Extra, result = z.z.Lookup(state, qname) m.Answer, m.Ns, m.Extra, result = z.z.Lookup(state, qname)
h.zMu.RUnlock() h.zMu.RUnlock()
if len(m.Answer) == 0 && h.Fall.Through(qname) {
return plugin.NextOrFailure(h.Name(), h.Next, ctx, w, r)
}
switch result { switch result {
case file.Success: case file.Success:
case file.NoData: case file.NoData:

View File

@@ -7,8 +7,10 @@ import (
"testing" "testing"
"github.com/coredns/coredns/plugin/pkg/dnstest" "github.com/coredns/coredns/plugin/pkg/dnstest"
"github.com/coredns/coredns/plugin/pkg/fall"
"github.com/coredns/coredns/plugin/pkg/upstream" "github.com/coredns/coredns/plugin/pkg/upstream"
"github.com/coredns/coredns/plugin/test" "github.com/coredns/coredns/plugin/test"
crequest "github.com/coredns/coredns/request"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/request" "github.com/aws/aws-sdk-go/aws/request"
@@ -75,7 +77,29 @@ func TestRoute53(t *testing.T) {
if err != nil { if err != nil {
t.Fatalf("Failed to create Route53: %v", err) t.Fatalf("Failed to create Route53: %v", err)
} }
r.Next = test.ErrorHandler() r.Fall = fall.Zero
r.Fall.SetZonesFromArgs([]string{"gov."})
r.Next = test.HandlerFunc(func(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
state := crequest.Request{W: w, Req: r}
qname := state.Name()
m := new(dns.Msg)
rcode := dns.RcodeServerFailure
if qname == "example.gov." {
m.SetReply(r)
rr, err := dns.NewRR("example.gov. 300 IN A 2.4.6.8")
if err != nil {
t.Fatalf("Failed to create Resource Record: %v", err)
}
m.Answer = []dns.RR{rr}
m.Authoritative, m.RecursionAvailable = true, true
rcode = dns.RcodeSuccess
}
m.SetRcode(r, rcode)
w.WriteMsg(m)
return rcode, nil
})
err = r.Run(ctx) err = r.Run(ctx)
if err != nil { if err != nil {
t.Fatalf("Failed to initialize Route53: %v", err) t.Fatalf("Failed to initialize Route53: %v", err)
@@ -156,6 +180,13 @@ func TestRoute53(t *testing.T) {
expectedCode: dns.RcodeSuccess, expectedCode: dns.RcodeSuccess,
wantNS: []string{"org. 300 IN SOA ns-1536.awsdns-00.co.uk. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400"}, wantNS: []string{"org. 300 IN SOA ns-1536.awsdns-00.co.uk. awsdns-hostmaster.amazon.com. 1 7200 900 1209600 86400"},
}, },
// 9. No record found. Fallthrough.
{
qname: "example.gov",
qtype: dns.TypeA,
expectedCode: dns.RcodeSuccess,
wantAnswer: []string{"example.gov. 300 IN A 2.4.6.8"},
},
} }
for ti, tc := range tests { for ti, tc := range tests {

View File

@@ -6,6 +6,7 @@ import (
"github.com/coredns/coredns/core/dnsserver" "github.com/coredns/coredns/core/dnsserver"
"github.com/coredns/coredns/plugin" "github.com/coredns/coredns/plugin"
"github.com/coredns/coredns/plugin/pkg/fall"
clog "github.com/coredns/coredns/plugin/pkg/log" clog "github.com/coredns/coredns/plugin/pkg/log"
"github.com/coredns/coredns/plugin/pkg/upstream" "github.com/coredns/coredns/plugin/pkg/upstream"
@@ -36,6 +37,8 @@ func init() {
func setup(c *caddy.Controller, f func(*credentials.Credentials) route53iface.Route53API) error { func setup(c *caddy.Controller, f func(*credentials.Credentials) route53iface.Route53API) error {
keys := map[string]string{} keys := map[string]string{}
credential := credentials.NewEnvCredentials() credential := credentials.NewEnvCredentials()
var fall fall.F
up, _ := upstream.New(nil) up, _ := upstream.New(nil)
for c.Next() { for c.Next() {
args := c.RemainingArgs() args := c.RemainingArgs()
@@ -75,6 +78,8 @@ func setup(c *caddy.Controller, f func(*credentials.Credentials) route53iface.Ro
if err != nil { if err != nil {
return c.Errf("invalid upstream: %v", err) return c.Errf("invalid upstream: %v", err)
} }
case "fallthrough":
fall.SetZonesFromArgs(c.RemainingArgs())
default: default:
return c.Errf("unknown property '%s'", c.Val()) return c.Errf("unknown property '%s'", c.Val())
} }
@@ -86,6 +91,7 @@ func setup(c *caddy.Controller, f func(*credentials.Credentials) route53iface.Ro
if err != nil { if err != nil {
return c.Errf("failed to create Route53 plugin: %v", err) return c.Errf("failed to create Route53 plugin: %v", err)
} }
h.Fall = fall
if err := h.Run(ctx); err != nil { if err := h.Run(ctx); err != nil {
return c.Errf("failed to initialize Route53 plugin: %v", err) return c.Errf("failed to initialize Route53 plugin: %v", err)
} }

View File

@@ -52,6 +52,9 @@ func TestSetupRoute53(t *testing.T) {
c = caddy.NewTestController("dns", `route53 example.org:12345678 { c = caddy.NewTestController("dns", `route53 example.org:12345678 {
aws_access_key ACCESS_KEY_ID SEKRIT_ACCESS_KEY aws_access_key ACCESS_KEY_ID SEKRIT_ACCESS_KEY
upstream 1.2.3.4 upstream 1.2.3.4
}`)
c = caddy.NewTestController("dns", `route53 example.org:12345678 {
fallthrough
}`) }`)
if err := setup(c, f); err != nil { if err := setup(c, f); err != nil {
t.Fatalf("Unexpected errors: %v", err) t.Fatalf("Unexpected errors: %v", err)