mirror of
https://github.com/coredns/coredns.git
synced 2025-12-19 00:25:11 -05:00
Add new plugin: traffic
Traffic is a plugin that communicates via the xDS protocol to an Envoy control plane. Using the data from this control plane it hands out IP addresses. This allows you (via controlling the data in the control plane) to drain or send more traffic to specific endpoints. The plugin itself only acts upon this data; it doesn't do anything fancy by itself. Code used here is copied from grpc-go and other places, this is clearly marked in the source files. Signed-off-by: Miek Gieben <miek@miek.nl>
This commit is contained in:
93
plugin/traffic/traffic.go
Normal file
93
plugin/traffic/traffic.go
Normal file
@@ -0,0 +1,93 @@
|
||||
package traffic
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/coredns/coredns/plugin"
|
||||
"github.com/coredns/coredns/plugin/pkg/dnsutil"
|
||||
"github.com/coredns/coredns/plugin/traffic/xds"
|
||||
"github.com/coredns/coredns/request"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
// Traffic is a plugin that load balances according to assignments.
|
||||
type Traffic struct {
|
||||
c *xds.Client
|
||||
id string
|
||||
origins []string
|
||||
|
||||
Next plugin.Handler
|
||||
}
|
||||
|
||||
// ServeDNS implements the plugin.Handler interface.
|
||||
func (t *Traffic) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) (int, error) {
|
||||
state := request.Request{Req: r, W: w}
|
||||
|
||||
cluster := ""
|
||||
for _, o := range t.origins {
|
||||
if strings.HasSuffix(state.Name(), o) {
|
||||
cluster, _ = dnsutil.TrimZone(state.Name(), o)
|
||||
state.Zone = o
|
||||
break
|
||||
}
|
||||
}
|
||||
m := new(dns.Msg)
|
||||
m.SetReply(r)
|
||||
m.Authoritative = true
|
||||
|
||||
addr, ok := t.c.Select(cluster)
|
||||
if !ok {
|
||||
m.Ns = soa(state.Zone)
|
||||
m.Rcode = dns.RcodeNameError
|
||||
w.WriteMsg(m)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
if addr == nil {
|
||||
log.Debugf("No (healthy) endpoints found for %q", cluster)
|
||||
m.Ns = soa(state.Zone)
|
||||
w.WriteMsg(m)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
switch state.QType() {
|
||||
case dns.TypeA:
|
||||
if addr.To4() == nil { // it's an IPv6 address, return nodata in that case.
|
||||
m.Ns = soa(state.Zone)
|
||||
break
|
||||
}
|
||||
m.Answer = []dns.RR{&dns.A{Hdr: dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 5}, A: addr}}
|
||||
|
||||
case dns.TypeAAAA:
|
||||
if addr.To4() != nil { // it's an IPv4 address, return nodata in that case.
|
||||
m.Ns = soa(state.Zone)
|
||||
break
|
||||
}
|
||||
m.Answer = []dns.RR{&dns.AAAA{Hdr: dns.RR_Header{Name: state.QName(), Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 5}, AAAA: addr}}
|
||||
default:
|
||||
m.Ns = soa(state.Zone)
|
||||
}
|
||||
|
||||
w.WriteMsg(m)
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
// soa returns a synthetic so for this zone.
|
||||
func soa(z string) []dns.RR {
|
||||
return []dns.RR{&dns.SOA{
|
||||
Hdr: dns.RR_Header{Name: z, Rrtype: dns.TypeSOA, Class: dns.ClassINET, Ttl: 5},
|
||||
Ns: dnsutil.Join("ns", z),
|
||||
Mbox: dnsutil.Join("coredns", z),
|
||||
Serial: uint32(time.Now().UTC().Unix()),
|
||||
Refresh: 14400,
|
||||
Retry: 3600,
|
||||
Expire: 604800,
|
||||
Minttl: 5,
|
||||
}}
|
||||
}
|
||||
|
||||
// Name implements the plugin.Handler interface.
|
||||
func (t *Traffic) Name() string { return "traffic" }
|
||||
Reference in New Issue
Block a user