diff options
Diffstat (limited to 'middleware/federation/federation.go')
-rw-r--r-- | middleware/federation/federation.go | 141 |
1 files changed, 0 insertions, 141 deletions
diff --git a/middleware/federation/federation.go b/middleware/federation/federation.go deleted file mode 100644 index bc74d9fc9..000000000 --- a/middleware/federation/federation.go +++ /dev/null @@ -1,141 +0,0 @@ -/* -Package federation implements kubernetes federation. It checks if the qname matches -a possible federation. If this is the case and the captured answer is an NXDOMAIN, -federation is performed. If this is not the case the original answer is returned. - -The federation label is always the 2nd to last once the zone is chopped of. For -instance "nginx.mynamespace.myfederation.svc.example.com" has "myfederation" as -the federation label. For federation to work we do a normal k8s lookup -*without* that label, if that comes back with NXDOMAIN or NODATA(??) we create -a federation record and return that. - -Federation is only useful in conjunction with the kubernetes middleware, without it is a noop. -*/ -package federation - -import ( - "github.com/coredns/coredns/middleware" - "github.com/coredns/coredns/middleware/etcd/msg" - "github.com/coredns/coredns/middleware/pkg/dnsutil" - "github.com/coredns/coredns/middleware/pkg/nonwriter" - "github.com/coredns/coredns/request" - - "github.com/miekg/dns" - "golang.org/x/net/context" -) - -// Federation contains the name to zone mapping used for federation in kubernetes. -type Federation struct { - f map[string]string - zones []string - - Next middleware.Handler - Federations Func -} - -// Func needs to be implemented by any middleware that implements -// federation. Right now this is only the kubernetes middleware. -type Func func(state request.Request, fname, fzone string) (msg.Service, error) - -// New returns a new federation. -func New() *Federation { - return &Federation{f: make(map[string]string)} -} - -// ServeDNS implements the middleware.Handle interface. -func (f *Federation) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) { - if f.Federations == nil { - return middleware.NextOrFailure(f.Name(), f.Next, ctx, w, r) - } - - state := request.Request{W: w, Req: r} - zone := middleware.Zones(f.zones).Matches(state.Name()) - if zone == "" { - return middleware.NextOrFailure(f.Name(), f.Next, ctx, w, r) - } - - state.Zone = zone - - // Remove the federation label from the qname to see if something exists. - without, label := f.isNameFederation(state.Name(), state.Zone) - if without == "" { - return middleware.NextOrFailure(f.Name(), f.Next, ctx, w, r) - } - - qname := r.Question[0].Name - r.Question[0].Name = without - state.Clear() - - // Start the next middleware, but with a nowriter, capture the result, if NXDOMAIN - // perform federation, otherwise just write the result. - nw := nonwriter.New(w) - ret, err := middleware.NextOrFailure(f.Name(), f.Next, ctx, nw, r) - - if !middleware.ClientWrite(ret) { - // something went wrong - r.Question[0].Name = qname - return ret, err - } - - if m := nw.Msg; m.Rcode != dns.RcodeNameError { - // If positive answer we need to substitute the original qname in the answer. - m.Question[0].Name = qname - for _, a := range m.Answer { - a.Header().Name = qname - } - - state.SizeAndDo(m) - m, _ = state.Scrub(m) - w.WriteMsg(m) - - return dns.RcodeSuccess, nil - } - - // Still here, we've seen NXDOMAIN and need to perform federation. - service, err := f.Federations(state, label, f.f[label]) // state references Req which has updated qname - if err != nil { - r.Question[0].Name = qname - return dns.RcodeServerFailure, err - } - - r.Question[0].Name = qname - - m := new(dns.Msg) - m.SetReply(r) - m.Authoritative, m.RecursionAvailable, m.Compress = true, true, true - - m.Answer = []dns.RR{service.NewCNAME(state.QName(), service.Host)} - - state.SizeAndDo(m) - m, _ = state.Scrub(m) - w.WriteMsg(m) - - return dns.RcodeSuccess, nil -} - -// Name implements the middleware.Handle interface. -func (f *Federation) Name() string { return "federation" } - -// IsNameFederation checks the qname to see if it is a potential federation. The federation -// label is always the 2nd to last once the zone is chopped of. For instance -// "nginx.mynamespace.myfederation.svc.example.com" has "myfederation" as the federation label. -// IsNameFederation returns a new qname with the federation label and the label itself or two -// empty strings if there wasn't a hit. -func (f *Federation) isNameFederation(name, zone string) (string, string) { - base, _ := dnsutil.TrimZone(name, zone) - - // TODO(miek): dns.PrevLabel is better for memory, or dns.Split. - labels := dns.SplitDomainName(base) - ll := len(labels) - if ll < 2 { - return "", "" - } - - fed := labels[ll-2] - - if _, ok := f.f[fed]; ok { - without := dnsutil.Join(labels[:ll-2]) + labels[ll-1] + "." + zone - return without, fed - } - return "", "" -} |