WIP: Parserequest2 cutback (#868)
* middleware/kubernetes: pull TXT out of parseRequest Put the TXT handling one layer higher and remove it from parseRequest. Also rename the podsvc field in there to podOrSvc. Now that it isn't used anymore for TXT record (dns-version) that was put in there. We can make this a boolean (in a future PR). Make parseRequest get an optional Zone that is from state.Zone and use that instead of its own code. Removed some tests and other smaller cleanups. Fixes #836 * add this reverse * another check * readd * Rename to kPod and kService for some clarity
This commit is contained in:
parent
fefc4374d7
commit
7e56cc74e5
9 changed files with 317 additions and 328 deletions
|
@ -62,13 +62,13 @@ func (k *Kubernetes) federationCNAMERecord(r recordRequest) msg.Service {
|
||||||
}
|
}
|
||||||
if r.endpoint == "" {
|
if r.endpoint == "" {
|
||||||
return msg.Service{
|
return msg.Service{
|
||||||
Key: strings.Join([]string{msg.Path(r.zone, "coredns"), r.typeName, r.federation, r.namespace, r.service}, "/"),
|
Key: strings.Join([]string{msg.Path(r.zone, "coredns"), r.podOrSvc, r.federation, r.namespace, r.service}, "/"),
|
||||||
Host: strings.Join([]string{r.service, r.namespace, r.federation, r.typeName, node.Labels[labelAvailabilityZone], node.Labels[labelRegion], f.zone}, "."),
|
Host: strings.Join([]string{r.service, r.namespace, r.federation, r.podOrSvc, node.Labels[labelAvailabilityZone], node.Labels[labelRegion], f.zone}, "."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return msg.Service{
|
return msg.Service{
|
||||||
Key: strings.Join([]string{msg.Path(r.zone, "coredns"), r.typeName, r.federation, r.namespace, r.service, r.endpoint}, "/"),
|
Key: strings.Join([]string{msg.Path(r.zone, "coredns"), r.podOrSvc, r.federation, r.namespace, r.service, r.endpoint}, "/"),
|
||||||
Host: strings.Join([]string{r.endpoint, r.service, r.namespace, r.federation, r.typeName, node.Labels[labelAvailabilityZone], node.Labels[labelRegion], f.zone}, "."),
|
Host: strings.Join([]string{r.endpoint, r.service, r.namespace, r.federation, r.podOrSvc, node.Labels[labelAvailabilityZone], node.Labels[labelRegion], f.zone}, "."),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,17 +85,17 @@ func testFederationCNAMERecord(t *testing.T, k Kubernetes, input recordRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestFederationCNAMERecord(t *testing.T) {
|
func TestFederationCNAMERecord(t *testing.T) {
|
||||||
k := Kubernetes{Zones: []string{"inter.webs"}}
|
k := Kubernetes{Zones: []string{"inter.webs."}}
|
||||||
k.Federations = []Federation{{name: "fed", zone: "era.tion.com"}}
|
k.Federations = []Federation{{name: "fed", zone: "era.tion.com"}}
|
||||||
k.APIConn = apiConnFedTest{}
|
k.APIConn = apiConnFedTest{}
|
||||||
k.interfaceAddrsFunc = func() net.IP { return net.ParseIP("10.9.8.7") }
|
k.interfaceAddrsFunc = func() net.IP { return net.ParseIP("10.9.8.7") }
|
||||||
|
|
||||||
r, _ := k.parseRequest("s1.ns.fed.svc.inter.webs", dns.TypeA)
|
r, _ := k.parseRequest("s1.ns.fed.svc.inter.webs.", dns.TypeA, "inter.webs.")
|
||||||
testFederationCNAMERecord(t, k, r, msg.Service{Key: "/coredns/webs/inter/svc/fed/ns/s1", Host: "s1.ns.fed.svc.fd-az.fd-r.era.tion.com"})
|
testFederationCNAMERecord(t, k, r, msg.Service{Key: "/coredns/webs/inter/svc/fed/ns/s1", Host: "s1.ns.fed.svc.fd-az.fd-r.era.tion.com"})
|
||||||
|
|
||||||
r, _ = k.parseRequest("ep1.s1.ns.fed.svc.inter.webs", dns.TypeA)
|
r, _ = k.parseRequest("ep1.s1.ns.fed.svc.inter.webs.", dns.TypeA, "inter.webs.")
|
||||||
testFederationCNAMERecord(t, k, r, msg.Service{Key: "/coredns/webs/inter/svc/fed/ns/s1/ep1", Host: "ep1.s1.ns.fed.svc.fd-az.fd-r.era.tion.com"})
|
testFederationCNAMERecord(t, k, r, msg.Service{Key: "/coredns/webs/inter/svc/fed/ns/s1/ep1", Host: "ep1.s1.ns.fed.svc.fd-az.fd-r.era.tion.com"})
|
||||||
|
|
||||||
r, _ = k.parseRequest("ep1.s1.ns.foo.svc.inter.webs", dns.TypeA)
|
r, _ = k.parseRequest("ep1.s1.ns.foo.svc.inter.webs.", dns.TypeA, "inter.webs.")
|
||||||
testFederationCNAMERecord(t, k, r, msg.Service{Key: "", Host: ""})
|
testFederationCNAMERecord(t, k, r, msg.Service{Key: "", Host: ""})
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,10 +34,13 @@ func (k Kubernetes) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.M
|
||||||
if !k.isRequestInReverseRange(state.Name()) {
|
if !k.isRequestInReverseRange(state.Name()) {
|
||||||
return middleware.NextOrFailure(k.Name(), k.Next, ctx, w, r)
|
return middleware.NextOrFailure(k.Name(), k.Next, ctx, w, r)
|
||||||
}
|
}
|
||||||
// Set the zone to this specific request.
|
|
||||||
|
// Set the zone to this specific request, as we want to handle this reverse request.
|
||||||
zone = state.Name()
|
zone = state.Name()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state.Zone = zone
|
||||||
|
|
||||||
var (
|
var (
|
||||||
records []dns.RR
|
records []dns.RR
|
||||||
extra []dns.RR
|
extra []dns.RR
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
|
|
||||||
"github.com/coredns/coredns/middleware"
|
"github.com/coredns/coredns/middleware"
|
||||||
"github.com/coredns/coredns/middleware/etcd/msg"
|
"github.com/coredns/coredns/middleware/etcd/msg"
|
||||||
|
"github.com/coredns/coredns/middleware/pkg/dnsutil"
|
||||||
dnsstrings "github.com/coredns/coredns/middleware/pkg/strings"
|
dnsstrings "github.com/coredns/coredns/middleware/pkg/strings"
|
||||||
"github.com/coredns/coredns/middleware/proxy"
|
"github.com/coredns/coredns/middleware/proxy"
|
||||||
"github.com/coredns/coredns/request"
|
"github.com/coredns/coredns/request"
|
||||||
|
@ -64,7 +65,8 @@ type endpoint struct {
|
||||||
port api.EndpointPort
|
port api.EndpointPort
|
||||||
}
|
}
|
||||||
|
|
||||||
type service struct {
|
// kService is a service as retrieved via the k8s API.
|
||||||
|
type kService struct {
|
||||||
name string
|
name string
|
||||||
namespace string
|
namespace string
|
||||||
addr string
|
addr string
|
||||||
|
@ -72,23 +74,13 @@ type service struct {
|
||||||
endpoints []endpoint
|
endpoints []endpoint
|
||||||
}
|
}
|
||||||
|
|
||||||
type pod struct {
|
// kPod is a pod as retrieved via the k8s API.
|
||||||
|
type kPod struct {
|
||||||
name string
|
name string
|
||||||
namespace string
|
namespace string
|
||||||
addr string
|
addr string
|
||||||
}
|
}
|
||||||
|
|
||||||
type recordRequest struct {
|
|
||||||
port string
|
|
||||||
protocol string
|
|
||||||
endpoint string
|
|
||||||
service string
|
|
||||||
namespace string
|
|
||||||
typeName string
|
|
||||||
zone string
|
|
||||||
federation string
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errNoItems = errors.New("no items found")
|
errNoItems = errors.New("no items found")
|
||||||
errNsNotExposed = errors.New("namespace is not exposed")
|
errNsNotExposed = errors.New("namespace is not exposed")
|
||||||
|
@ -100,12 +92,33 @@ var (
|
||||||
|
|
||||||
// Services implements the ServiceBackend interface.
|
// Services implements the ServiceBackend interface.
|
||||||
func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.Options) (svcs []msg.Service, debug []msg.Service, err error) {
|
func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.Options) (svcs []msg.Service, debug []msg.Service, err error) {
|
||||||
r, e := k.parseRequest(state.Name(), state.QType())
|
|
||||||
|
// We're looking again at types, which we've already done in ServeDNS, but there are some types k8s just can't answer.
|
||||||
|
switch state.QType() {
|
||||||
|
case dns.TypeTXT:
|
||||||
|
// 1 label + zone, label must be "dns-version"
|
||||||
|
t, err := dnsutil.TrimZone(state.Name(), state.Zone)
|
||||||
|
if err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
segs := dns.SplitDomainName(t)
|
||||||
|
if len(segs) != 1 {
|
||||||
|
return nil, nil, errors.New("servfail")
|
||||||
|
}
|
||||||
|
if segs[0] != "dns-version" {
|
||||||
|
return nil, nil, errInvalidRequest
|
||||||
|
}
|
||||||
|
svc := msg.Service{Text: DNSSchemaVersion, TTL: 28800, Key: msg.Path(state.QName(), "coredns")}
|
||||||
|
return []msg.Service{svc}, nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
r, e := k.parseRequest(state.Name(), state.QType(), state.Zone)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
return nil, nil, e
|
return nil, nil, e
|
||||||
}
|
}
|
||||||
switch state.Type() {
|
|
||||||
case "A", "AAAA", "CNAME":
|
switch state.QType() {
|
||||||
|
case dns.TypeA, dns.TypeAAAA, dns.TypeCNAME:
|
||||||
if state.Type() == "A" && isDefaultNS(state.Name(), r) {
|
if state.Type() == "A" && isDefaultNS(state.Name(), r) {
|
||||||
// If this is an A request for "ns.dns", respond with a "fake" record for coredns.
|
// If this is an A request for "ns.dns", respond with a "fake" record for coredns.
|
||||||
// SOA records always use this hardcoded name
|
// SOA records always use this hardcoded name
|
||||||
|
@ -118,7 +131,7 @@ func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.
|
||||||
return nil, nil, e
|
return nil, nil, e
|
||||||
}
|
}
|
||||||
return s, nil, e // Haven't implemented debug queries yet.
|
return s, nil, e // Haven't implemented debug queries yet.
|
||||||
case "SRV":
|
case dns.TypeSRV:
|
||||||
s, e := k.Entries(r)
|
s, e := k.Entries(r)
|
||||||
// SRV for external services is not yet implemented, so remove those records
|
// SRV for external services is not yet implemented, so remove those records
|
||||||
noext := []msg.Service{}
|
noext := []msg.Service{}
|
||||||
|
@ -128,13 +141,7 @@ func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return noext, nil, e
|
return noext, nil, e
|
||||||
case "TXT":
|
case dns.TypeNS:
|
||||||
if r.typeName == "dns-version" {
|
|
||||||
srv := k.recordsForTXT(r)
|
|
||||||
svcs = append(svcs, srv)
|
|
||||||
}
|
|
||||||
return svcs, nil, err
|
|
||||||
case "NS":
|
|
||||||
srv := k.recordsForNS(r)
|
srv := k.recordsForNS(r)
|
||||||
svcs = append(svcs, srv)
|
svcs = append(svcs, srv)
|
||||||
return svcs, nil, err
|
return svcs, nil, err
|
||||||
|
@ -142,11 +149,6 @@ func (k *Kubernetes) Services(state request.Request, exact bool, opt middleware.
|
||||||
return nil, nil, nil
|
return nil, nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Kubernetes) recordsForTXT(r recordRequest) msg.Service {
|
|
||||||
return msg.Service{Text: DNSSchemaVersion, TTL: 28800,
|
|
||||||
Key: msg.Path(strings.Join([]string{r.typeName, r.zone}, "."), "coredns")}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (k *Kubernetes) recordsForNS(r recordRequest) msg.Service {
|
func (k *Kubernetes) recordsForNS(r recordRequest) msg.Service {
|
||||||
ns := k.coreDNSRecord()
|
ns := k.coreDNSRecord()
|
||||||
return msg.Service{Host: ns.A.String(),
|
return msg.Service{Host: ns.A.String(),
|
||||||
|
@ -234,99 +236,6 @@ func (k *Kubernetes) InitKubeCache() (err error) {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Kubernetes) parseRequest(lowerCasedName string, qtype uint16) (r recordRequest, err error) {
|
|
||||||
// 3 Possible cases
|
|
||||||
// SRV Request: _port._protocol.service.namespace.[federation.]type.zone
|
|
||||||
// A Request (endpoint): endpoint.service.namespace.[federation.]type.zone
|
|
||||||
// A Request (service): service.namespace.[federation.]type.zone
|
|
||||||
|
|
||||||
// separate zone from rest of lowerCasedName
|
|
||||||
var segs []string
|
|
||||||
for _, z := range k.Zones {
|
|
||||||
if dns.IsSubDomain(z, lowerCasedName) {
|
|
||||||
r.zone = z
|
|
||||||
|
|
||||||
segs = dns.SplitDomainName(lowerCasedName)
|
|
||||||
segs = segs[:len(segs)-dns.CountLabel(r.zone)]
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if r.zone == "" {
|
|
||||||
return r, errZoneNotFound
|
|
||||||
}
|
|
||||||
|
|
||||||
r.federation, segs = k.stripFederation(segs)
|
|
||||||
|
|
||||||
if qtype == dns.TypeNS {
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if qtype == dns.TypeA && isDefaultNS(lowerCasedName, r) {
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
offset := 0
|
|
||||||
if qtype == dns.TypeSRV {
|
|
||||||
// The kubernetes peer-finder expects queries with empty port and service to resolve
|
|
||||||
// If neither is specified, treat it as a wildcard
|
|
||||||
if len(segs) == 3 {
|
|
||||||
r.port = "*"
|
|
||||||
r.service = "*"
|
|
||||||
offset = 0
|
|
||||||
} else {
|
|
||||||
if len(segs) != 5 {
|
|
||||||
return r, errInvalidRequest
|
|
||||||
}
|
|
||||||
// This is a SRV style request, get first two elements as port and
|
|
||||||
// protocol, stripping leading underscores if present.
|
|
||||||
if segs[0][0] == '_' {
|
|
||||||
r.port = segs[0][1:]
|
|
||||||
} else {
|
|
||||||
r.port = segs[0]
|
|
||||||
if !wildcard(r.port) {
|
|
||||||
return r, errInvalidRequest
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if segs[1][0] == '_' {
|
|
||||||
r.protocol = segs[1][1:]
|
|
||||||
if r.protocol != "tcp" && r.protocol != "udp" {
|
|
||||||
return r, errInvalidRequest
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
r.protocol = segs[1]
|
|
||||||
if !wildcard(r.protocol) {
|
|
||||||
return r, errInvalidRequest
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if r.port == "" || r.protocol == "" {
|
|
||||||
return r, errInvalidRequest
|
|
||||||
}
|
|
||||||
offset = 2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (qtype == dns.TypeA || qtype == dns.TypeAAAA) && len(segs) == 4 {
|
|
||||||
// This is an endpoint A/AAAA record request. Get first element as endpoint.
|
|
||||||
r.endpoint = segs[0]
|
|
||||||
offset = 1
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(segs) == (offset + 3) {
|
|
||||||
r.service = segs[offset]
|
|
||||||
r.namespace = segs[offset+1]
|
|
||||||
r.typeName = segs[offset+2]
|
|
||||||
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(segs) == 1 && qtype == dns.TypeTXT {
|
|
||||||
r.typeName = segs[0]
|
|
||||||
return r, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return r, errInvalidRequest
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// Records not implemented, see Entries().
|
// Records not implemented, see Entries().
|
||||||
func (k *Kubernetes) Records(name string, exact bool) ([]msg.Service, error) {
|
func (k *Kubernetes) Records(name string, exact bool) ([]msg.Service, error) {
|
||||||
return nil, fmt.Errorf("NOOP")
|
return nil, fmt.Errorf("NOOP")
|
||||||
|
@ -375,7 +284,7 @@ func endpointHostname(addr api.EndpointAddress) string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Kubernetes) getRecordsForK8sItems(services []service, pods []pod, r recordRequest) (records []msg.Service) {
|
func (k *Kubernetes) getRecordsForK8sItems(services []kService, pods []kPod, r recordRequest) (records []msg.Service) {
|
||||||
zonePath := msg.Path(r.zone, "coredns")
|
zonePath := msg.Path(r.zone, "coredns")
|
||||||
|
|
||||||
for _, svc := range services {
|
for _, svc := range services {
|
||||||
|
@ -435,7 +344,7 @@ func (k *Kubernetes) getRecordsForK8sItems(services []service, pods []pod, r rec
|
||||||
return records
|
return records
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Kubernetes) findPods(namespace, podname string) (pods []pod, err error) {
|
func (k *Kubernetes) findPods(namespace, podname string) (pods []kPod, err error) {
|
||||||
if k.PodMode == PodModeDisabled {
|
if k.PodMode == PodModeDisabled {
|
||||||
return pods, errPodsDisabled
|
return pods, errPodsDisabled
|
||||||
}
|
}
|
||||||
|
@ -448,7 +357,7 @@ func (k *Kubernetes) findPods(namespace, podname string) (pods []pod, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
if k.PodMode == PodModeInsecure {
|
if k.PodMode == PodModeInsecure {
|
||||||
s := pod{name: podname, namespace: namespace, addr: ip}
|
s := kPod{name: podname, namespace: namespace, addr: ip}
|
||||||
pods = append(pods, s)
|
pods = append(pods, s)
|
||||||
return pods, nil
|
return pods, nil
|
||||||
}
|
}
|
||||||
|
@ -468,7 +377,7 @@ func (k *Kubernetes) findPods(namespace, podname string) (pods []pod, err error)
|
||||||
}
|
}
|
||||||
// check for matching ip and namespace
|
// check for matching ip and namespace
|
||||||
if ip == p.Status.PodIP && match(namespace, p.Namespace, nsWildcard) {
|
if ip == p.Status.PodIP && match(namespace, p.Namespace, nsWildcard) {
|
||||||
s := pod{name: podname, namespace: namespace, addr: ip}
|
s := kPod{name: podname, namespace: namespace, addr: ip}
|
||||||
pods = append(pods, s)
|
pods = append(pods, s)
|
||||||
return pods, nil
|
return pods, nil
|
||||||
}
|
}
|
||||||
|
@ -477,9 +386,9 @@ func (k *Kubernetes) findPods(namespace, podname string) (pods []pod, err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// get retrieves matching data from the cache.
|
// get retrieves matching data from the cache.
|
||||||
func (k *Kubernetes) get(r recordRequest) (services []service, pods []pod, err error) {
|
func (k *Kubernetes) get(r recordRequest) (services []kService, pods []kPod, err error) {
|
||||||
switch {
|
switch {
|
||||||
case r.typeName == Pod:
|
case r.podOrSvc == Pod:
|
||||||
pods, err = k.findPods(r.namespace, r.service)
|
pods, err = k.findPods(r.namespace, r.service)
|
||||||
return nil, pods, err
|
return nil, pods, err
|
||||||
default:
|
default:
|
||||||
|
@ -488,9 +397,9 @@ func (k *Kubernetes) get(r recordRequest) (services []service, pods []pod, err e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (k *Kubernetes) findServices(r recordRequest) ([]service, error) {
|
func (k *Kubernetes) findServices(r recordRequest) ([]kService, error) {
|
||||||
serviceList := k.APIConn.ServiceList()
|
serviceList := k.APIConn.ServiceList()
|
||||||
var resultItems []service
|
var resultItems []kService
|
||||||
|
|
||||||
nsWildcard := wildcard(r.namespace)
|
nsWildcard := wildcard(r.namespace)
|
||||||
serviceWildcard := wildcard(r.service)
|
serviceWildcard := wildcard(r.service)
|
||||||
|
@ -506,7 +415,7 @@ func (k *Kubernetes) findServices(r recordRequest) ([]service, error) {
|
||||||
if nsWildcard && (len(k.Namespaces) > 0) && (!dnsstrings.StringInSlice(svc.Namespace, k.Namespaces)) {
|
if nsWildcard && (len(k.Namespaces) > 0) && (!dnsstrings.StringInSlice(svc.Namespace, k.Namespaces)) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
s := service{name: svc.Name, namespace: svc.Namespace}
|
s := kService{name: svc.Name, namespace: svc.Namespace}
|
||||||
|
|
||||||
// Endpoint query or headless service
|
// Endpoint query or headless service
|
||||||
if svc.Spec.ClusterIP == api.ClusterIPNone || r.endpoint != "" {
|
if svc.Spec.ClusterIP == api.ClusterIPNone || r.endpoint != "" {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
package kubernetes
|
package kubernetes
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
|
||||||
"reflect"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/coredns/coredns/middleware"
|
"github.com/coredns/coredns/middleware"
|
||||||
|
@ -12,17 +10,6 @@ import (
|
||||||
"k8s.io/client-go/1.5/pkg/api"
|
"k8s.io/client-go/1.5/pkg/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRecordForTXT(t *testing.T) {
|
|
||||||
k := Kubernetes{Zones: []string{"inter.webs.test"}}
|
|
||||||
r, _ := k.parseRequest("dns-version.inter.webs.test", dns.TypeTXT)
|
|
||||||
|
|
||||||
expected := DNSSchemaVersion
|
|
||||||
svc := k.recordsForTXT(r)
|
|
||||||
if svc.Text != expected {
|
|
||||||
t.Errorf("Expected result '%v'. Instead got result '%v'.", expected, svc.Text)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestPrimaryZone(t *testing.T) {
|
func TestPrimaryZone(t *testing.T) {
|
||||||
k := Kubernetes{Zones: []string{"inter.webs.test", "inter.nets.test"}}
|
k := Kubernetes{Zones: []string{"inter.webs.test", "inter.nets.test"}}
|
||||||
expected := "inter.webs.test"
|
expected := "inter.webs.test"
|
||||||
|
@ -32,23 +19,6 @@ func TestPrimaryZone(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsNameError(t *testing.T) {
|
|
||||||
k := Kubernetes{Zones: []string{"inter.webs.test"}}
|
|
||||||
if !k.IsNameError(errNoItems) {
|
|
||||||
t.Errorf("Expected 'true' for '%v'", errNoItems)
|
|
||||||
}
|
|
||||||
if !k.IsNameError(errNsNotExposed) {
|
|
||||||
t.Errorf("Expected 'true' for '%v'", errNsNotExposed)
|
|
||||||
}
|
|
||||||
if !k.IsNameError(errInvalidRequest) {
|
|
||||||
t.Errorf("Expected 'true' for '%v'", errInvalidRequest)
|
|
||||||
}
|
|
||||||
otherErr := errors.New("Some other error occurred")
|
|
||||||
if k.IsNameError(otherErr) {
|
|
||||||
t.Errorf("Expected 'true' for '%v'", otherErr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestWildcard(t *testing.T) {
|
func TestWildcard(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
s string
|
s string
|
||||||
|
@ -70,151 +40,6 @@ func TestWildcard(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func expectString(t *testing.T, function, qtype, query string, r *recordRequest, field, expected string) {
|
|
||||||
ref := reflect.ValueOf(r)
|
|
||||||
refField := reflect.Indirect(ref).FieldByName(field)
|
|
||||||
got := refField.String()
|
|
||||||
if got != expected {
|
|
||||||
t.Errorf("Expected %v(%v, \"%v\") to get %v == \"%v\". Instead got \"%v\".", function, query, qtype, field, expected, got)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestParseRequest(t *testing.T) {
|
|
||||||
|
|
||||||
var tcs map[string]string
|
|
||||||
|
|
||||||
k := Kubernetes{Zones: []string{"inter.webs.test"}}
|
|
||||||
f := "parseRequest"
|
|
||||||
|
|
||||||
// Test a valid SRV request
|
|
||||||
//
|
|
||||||
query := "_http._tcp.webs.mynamespace.svc.inter.webs.test."
|
|
||||||
r, e := k.parseRequest(query, dns.TypeSRV)
|
|
||||||
if e != nil {
|
|
||||||
t.Errorf("Expected no error from parseRequest(%v, \"SRV\"). Instead got '%v'.", query, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
tcs = map[string]string{
|
|
||||||
"port": "http",
|
|
||||||
"protocol": "tcp",
|
|
||||||
"endpoint": "",
|
|
||||||
"service": "webs",
|
|
||||||
"namespace": "mynamespace",
|
|
||||||
"typeName": Svc,
|
|
||||||
"zone": "inter.webs.test",
|
|
||||||
}
|
|
||||||
for field, expected := range tcs {
|
|
||||||
expectString(t, f, "SRV", query, &r, field, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test wildcard acceptance
|
|
||||||
//
|
|
||||||
query = "*.any.*.any.svc.inter.webs.test."
|
|
||||||
r, e = k.parseRequest(query, dns.TypeSRV)
|
|
||||||
if e != nil {
|
|
||||||
t.Errorf("Expected no error from parseRequest(\"%v\", \"SRV\"). Instead got '%v'.", query, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
tcs = map[string]string{
|
|
||||||
"port": "*",
|
|
||||||
"protocol": "any",
|
|
||||||
"endpoint": "",
|
|
||||||
"service": "*",
|
|
||||||
"namespace": "any",
|
|
||||||
"typeName": Svc,
|
|
||||||
"zone": "inter.webs.test",
|
|
||||||
}
|
|
||||||
for field, expected := range tcs {
|
|
||||||
expectString(t, f, "SRV", query, &r, field, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test A request of endpoint
|
|
||||||
query = "1-2-3-4.webs.mynamespace.svc.inter.webs.test."
|
|
||||||
r, e = k.parseRequest(query, dns.TypeA)
|
|
||||||
if e != nil {
|
|
||||||
t.Errorf("Expected no error from parseRequest(\"%v\", \"A\"). Instead got '%v'.", query, e)
|
|
||||||
}
|
|
||||||
tcs = map[string]string{
|
|
||||||
"port": "",
|
|
||||||
"protocol": "",
|
|
||||||
"endpoint": "1-2-3-4",
|
|
||||||
"service": "webs",
|
|
||||||
"namespace": "mynamespace",
|
|
||||||
"typeName": Svc,
|
|
||||||
"zone": "inter.webs.test",
|
|
||||||
}
|
|
||||||
for field, expected := range tcs {
|
|
||||||
expectString(t, f, "A", query, &r, field, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test NS request
|
|
||||||
query = "inter.webs.test."
|
|
||||||
r, e = k.parseRequest(query, dns.TypeNS)
|
|
||||||
if e != nil {
|
|
||||||
t.Errorf("Expected no error from parseRequest(\"%v\", \"NS\"). Instead got '%v'.", query, e)
|
|
||||||
}
|
|
||||||
tcs = map[string]string{
|
|
||||||
"port": "",
|
|
||||||
"protocol": "",
|
|
||||||
"endpoint": "",
|
|
||||||
"service": "",
|
|
||||||
"namespace": "",
|
|
||||||
"typeName": "",
|
|
||||||
"zone": "inter.webs.test",
|
|
||||||
}
|
|
||||||
for field, expected := range tcs {
|
|
||||||
expectString(t, f, "NS", query, &r, field, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test TXT request
|
|
||||||
query = "dns-version.inter.webs.test."
|
|
||||||
r, e = k.parseRequest(query, dns.TypeTXT)
|
|
||||||
if e != nil {
|
|
||||||
t.Errorf("Expected no error from parseRequest(\"%v\", \"TXT\"). Instead got '%v'.", query, e)
|
|
||||||
}
|
|
||||||
tcs = map[string]string{
|
|
||||||
"port": "",
|
|
||||||
"protocol": "",
|
|
||||||
"endpoint": "",
|
|
||||||
"service": "",
|
|
||||||
"namespace": "",
|
|
||||||
"typeName": "dns-version",
|
|
||||||
"zone": "inter.webs.test",
|
|
||||||
}
|
|
||||||
for field, expected := range tcs {
|
|
||||||
expectString(t, f, "TXT", query, &r, field, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Invalid query tests
|
|
||||||
invalidAQueries := []string{
|
|
||||||
"_http._tcp.webs.mynamespace.svc.inter.webs.test.", // A requests cannot have port or protocol
|
|
||||||
"servname.ns1.srv.inter.nets.test.", // A requests must have zone that matches corefile
|
|
||||||
|
|
||||||
}
|
|
||||||
for _, q := range invalidAQueries {
|
|
||||||
_, e = k.parseRequest(q, dns.TypeA)
|
|
||||||
if e == nil {
|
|
||||||
t.Errorf("Expected error from %v(\"%v\", \"A\").", f, q)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
invalidSRVQueries := []string{
|
|
||||||
"_http._pcp.webs.mynamespace.svc.inter.webs.test.", // SRV protocol must be tcp or udp
|
|
||||||
"_http._tcp.ep.webs.ns.svc.inter.webs.test.", // SRV requests cannot have an endpoint
|
|
||||||
"_*._*.webs.mynamespace.svc.inter.webs.test.", // SRV request with invalid wildcards
|
|
||||||
"_http._tcp",
|
|
||||||
"_tcp.test.",
|
|
||||||
".",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, q := range invalidSRVQueries {
|
|
||||||
_, e = k.parseRequest(q, dns.TypeSRV)
|
|
||||||
if e == nil {
|
|
||||||
t.Errorf("Expected error from %v(\"%v\", \"SRV\").", f, q)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestEndpointHostname(t *testing.T) {
|
func TestEndpointHostname(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
ip string
|
ip string
|
||||||
|
@ -384,7 +209,7 @@ func (APIConnServiceTest) GetNodeByName(name string) (api.Node, error) {
|
||||||
|
|
||||||
func TestServices(t *testing.T) {
|
func TestServices(t *testing.T) {
|
||||||
|
|
||||||
k := Kubernetes{Zones: []string{"interwebs.test"}}
|
k := Kubernetes{Zones: []string{"interwebs.test."}}
|
||||||
k.Federations = []Federation{{name: "fed", zone: "era.tion.com"}}
|
k.Federations = []Federation{{name: "fed", zone: "era.tion.com"}}
|
||||||
k.interfaceAddrsFunc = localPodIP
|
k.interfaceAddrsFunc = localPodIP
|
||||||
k.APIConn = &APIConnServiceTest{}
|
k.APIConn = &APIConnServiceTest{}
|
||||||
|
@ -414,7 +239,8 @@ func TestServices(t *testing.T) {
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
state := request.Request{
|
state := request.Request{
|
||||||
Req: &dns.Msg{Question: []dns.Question{{Name: test.qname, Qtype: test.qtype}}},
|
Req: &dns.Msg{Question: []dns.Question{{Name: test.qname, Qtype: test.qtype}}},
|
||||||
|
Zone: "interwebs.test.", // must match from k.Zones[0]
|
||||||
}
|
}
|
||||||
svcs, _, e := k.Services(state, false, middleware.Options{})
|
svcs, _, e := k.Services(state, false, middleware.Options{})
|
||||||
if e != nil {
|
if e != nil {
|
||||||
|
|
|
@ -7,10 +7,10 @@ import "k8s.io/client-go/1.5/pkg/api"
|
||||||
import "github.com/miekg/dns"
|
import "github.com/miekg/dns"
|
||||||
|
|
||||||
func TestRecordForNS(t *testing.T) {
|
func TestRecordForNS(t *testing.T) {
|
||||||
k := Kubernetes{Zones: []string{"inter.webs.test"}}
|
k := Kubernetes{Zones: []string{"inter.webs.test."}}
|
||||||
corednsRecord.Hdr.Name = "coredns.kube-system."
|
corednsRecord.Hdr.Name = "coredns.kube-system."
|
||||||
corednsRecord.A = net.IP("1.2.3.4")
|
corednsRecord.A = net.IP("1.2.3.4")
|
||||||
r, _ := k.parseRequest("inter.webs.test", dns.TypeNS)
|
r, _ := k.parseRequest("inter.webs.test.", dns.TypeNS, "inter.webs.test.")
|
||||||
|
|
||||||
expected := "/coredns/test/webs/inter/kube-system/coredns"
|
expected := "/coredns/test/webs/inter/kube-system/coredns"
|
||||||
svc := k.recordsForNS(r)
|
svc := k.recordsForNS(r)
|
||||||
|
@ -20,10 +20,10 @@ func TestRecordForNS(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDefaultNSMsg(t *testing.T) {
|
func TestDefaultNSMsg(t *testing.T) {
|
||||||
k := Kubernetes{Zones: []string{"inter.webs.test"}}
|
k := Kubernetes{Zones: []string{"inter.webs.test."}}
|
||||||
corednsRecord.Hdr.Name = "coredns.kube-system."
|
corednsRecord.Hdr.Name = "coredns.kube-system."
|
||||||
corednsRecord.A = net.IP("1.2.3.4")
|
corednsRecord.A = net.IP("1.2.3.4")
|
||||||
r, _ := k.parseRequest("ns.dns.inter.webs.test", dns.TypeA)
|
r, _ := k.parseRequest("ns.dns.inter.webs.test.", dns.TypeA, "inter.webs.test.")
|
||||||
|
|
||||||
expected := "/coredns/test/webs/inter/dns/ns"
|
expected := "/coredns/test/webs/inter/dns/ns"
|
||||||
svc := k.defaultNSMsg(r)
|
svc := k.defaultNSMsg(r)
|
||||||
|
@ -33,13 +33,13 @@ func TestDefaultNSMsg(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIsDefaultNS(t *testing.T) {
|
func TestIsDefaultNS(t *testing.T) {
|
||||||
k := Kubernetes{Zones: []string{"inter.webs.test"}}
|
k := Kubernetes{Zones: []string{"inter.webs.test."}}
|
||||||
r, _ := k.parseRequest("ns.dns.inter.webs.test", dns.TypeA)
|
r, _ := k.parseRequest("ns.dns.inter.webs.test", dns.TypeA, "inter.webs.test.")
|
||||||
|
|
||||||
var name string
|
var name string
|
||||||
var expected bool
|
var expected bool
|
||||||
|
|
||||||
name = "ns.dns.inter.webs.test"
|
name = "ns.dns.inter.webs.test."
|
||||||
expected = true
|
expected = true
|
||||||
if isDefaultNS(name, r) != expected {
|
if isDefaultNS(name, r) != expected {
|
||||||
t.Errorf("Expected IsDefaultNS('%v') to be '%v'.", name, expected)
|
t.Errorf("Expected IsDefaultNS('%v') to be '%v'.", name, expected)
|
||||||
|
|
120
middleware/kubernetes/parse.go
Normal file
120
middleware/kubernetes/parse.go
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
package kubernetes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/coredns/coredns/middleware/pkg/dnsutil"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
type recordRequest struct {
|
||||||
|
// The named port from the kubernetes DNS spec, this is the service part (think _https) from a well formed
|
||||||
|
// SRV record.
|
||||||
|
port string
|
||||||
|
// The protocol is usually _udp or _tcp (if set), and comes from the protocol part of a well formed
|
||||||
|
// SRV record.
|
||||||
|
protocol string
|
||||||
|
endpoint string
|
||||||
|
service string
|
||||||
|
namespace string
|
||||||
|
// A each name can be for a pod or a service, here we track what we've seen. This value is true for
|
||||||
|
// pods and false for services. If we ever need to extend this well use a typed value.
|
||||||
|
podOrSvc string
|
||||||
|
zone string
|
||||||
|
federation string
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(miek): make it use request.Request.
|
||||||
|
func (k *Kubernetes) parseRequest(lowerCasedName string, qtype uint16, zone ...string) (r recordRequest, err error) {
|
||||||
|
// 3 Possible cases
|
||||||
|
// SRV Request: _port._protocol.service.namespace.[federation.]type.zone
|
||||||
|
// A Request (endpoint): endpoint.service.namespace.[federation.]type.zone
|
||||||
|
// A Request (service): service.namespace.[federation.]type.zone
|
||||||
|
|
||||||
|
if len(zone) == 0 {
|
||||||
|
panic("parseRequest must be called with a zone")
|
||||||
|
}
|
||||||
|
|
||||||
|
base, _ := dnsutil.TrimZone(lowerCasedName, zone[0])
|
||||||
|
segs := dns.SplitDomainName(base)
|
||||||
|
|
||||||
|
r.zone = zone[0]
|
||||||
|
r.federation, segs = k.stripFederation(segs)
|
||||||
|
|
||||||
|
if qtype == dns.TypeNS {
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if qtype == dns.TypeA && isDefaultNS(lowerCasedName, r) {
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
offset := 0
|
||||||
|
if qtype == dns.TypeSRV {
|
||||||
|
// The kubernetes peer-finder expects queries with empty port and service to resolve
|
||||||
|
// If neither is specified, treat it as a wildcard
|
||||||
|
if len(segs) == 3 {
|
||||||
|
r.port = "*"
|
||||||
|
r.service = "*"
|
||||||
|
offset = 0
|
||||||
|
} else {
|
||||||
|
if len(segs) != 5 {
|
||||||
|
return r, errInvalidRequest
|
||||||
|
}
|
||||||
|
// This is a SRV style request, get first two elements as port and
|
||||||
|
// protocol, stripping leading underscores if present.
|
||||||
|
if segs[0][0] == '_' {
|
||||||
|
r.port = segs[0][1:]
|
||||||
|
} else {
|
||||||
|
r.port = segs[0]
|
||||||
|
if !wildcard(r.port) {
|
||||||
|
return r, errInvalidRequest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if segs[1][0] == '_' {
|
||||||
|
r.protocol = segs[1][1:]
|
||||||
|
if r.protocol != "tcp" && r.protocol != "udp" {
|
||||||
|
return r, errInvalidRequest
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
r.protocol = segs[1]
|
||||||
|
if !wildcard(r.protocol) {
|
||||||
|
return r, errInvalidRequest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if r.port == "" || r.protocol == "" {
|
||||||
|
return r, errInvalidRequest
|
||||||
|
}
|
||||||
|
offset = 2
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (qtype == dns.TypeA || qtype == dns.TypeAAAA) && len(segs) == 4 {
|
||||||
|
// This is an endpoint A/AAAA record request. Get first element as endpoint.
|
||||||
|
r.endpoint = segs[0]
|
||||||
|
offset = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(segs) == (offset + 3) {
|
||||||
|
r.service = segs[offset]
|
||||||
|
r.namespace = segs[offset+1]
|
||||||
|
r.podOrSvc = segs[offset+2]
|
||||||
|
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return r, errInvalidRequest
|
||||||
|
}
|
||||||
|
|
||||||
|
// String return a string representation of r, it just returns all
|
||||||
|
// fields concatenated with dots.
|
||||||
|
// This is mostly used in tests.
|
||||||
|
func (r recordRequest) String() string {
|
||||||
|
s := r.port
|
||||||
|
s += "." + r.protocol
|
||||||
|
s += "." + r.endpoint
|
||||||
|
s += "." + r.service
|
||||||
|
s += "." + r.namespace
|
||||||
|
s += "." + r.podOrSvc
|
||||||
|
s += "." + r.zone
|
||||||
|
s += "." + r.federation
|
||||||
|
return s
|
||||||
|
}
|
131
middleware/kubernetes/parse_test.go
Normal file
131
middleware/kubernetes/parse_test.go
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
package kubernetes
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/miekg/dns"
|
||||||
|
)
|
||||||
|
|
||||||
|
func expectString(t *testing.T, function, qtype, query string, r *recordRequest, field, expected string) {
|
||||||
|
ref := reflect.ValueOf(r)
|
||||||
|
refField := reflect.Indirect(ref).FieldByName(field)
|
||||||
|
got := refField.String()
|
||||||
|
if got != expected {
|
||||||
|
t.Errorf("Expected %v(%v, \"%v\") to get %v == \"%v\". Instead got \"%v\".", function, query, qtype, field, expected, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestParseRequest(t *testing.T) {
|
||||||
|
|
||||||
|
var tcs map[string]string
|
||||||
|
|
||||||
|
zone := "intern.webs.tests."
|
||||||
|
k := Kubernetes{Zones: []string{zone}}
|
||||||
|
f := "parseRequest"
|
||||||
|
|
||||||
|
// Test a valid SRV request
|
||||||
|
//
|
||||||
|
query := "_http._tcp.webs.mynamespace.svc.inter.webs.test."
|
||||||
|
r, e := k.parseRequest(query, dns.TypeSRV, zone)
|
||||||
|
if e != nil {
|
||||||
|
t.Errorf("Expected no error from parseRequest(%v, \"SRV\"). Instead got '%v'.", query, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
tcs = map[string]string{
|
||||||
|
"port": "http",
|
||||||
|
"protocol": "tcp",
|
||||||
|
"endpoint": "",
|
||||||
|
"service": "webs",
|
||||||
|
"namespace": "mynamespace",
|
||||||
|
"podOrSvc": Svc,
|
||||||
|
"zone": zone,
|
||||||
|
}
|
||||||
|
for field, expected := range tcs {
|
||||||
|
expectString(t, f, "SRV", query, &r, field, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test wildcard acceptance
|
||||||
|
//
|
||||||
|
query = "*.any.*.any.svc.inter.webs.test."
|
||||||
|
r, e = k.parseRequest(query, dns.TypeSRV, zone)
|
||||||
|
if e != nil {
|
||||||
|
t.Errorf("Expected no error from parseRequest(\"%v\", \"SRV\"). Instead got '%v'.", query, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
tcs = map[string]string{
|
||||||
|
"port": "*",
|
||||||
|
"protocol": "any",
|
||||||
|
"endpoint": "",
|
||||||
|
"service": "*",
|
||||||
|
"namespace": "any",
|
||||||
|
"podOrSvc": Svc,
|
||||||
|
"zone": zone,
|
||||||
|
}
|
||||||
|
for field, expected := range tcs {
|
||||||
|
expectString(t, f, "SRV", query, &r, field, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test A request of endpoint
|
||||||
|
query = "1-2-3-4.webs.mynamespace.svc.inter.webs.test."
|
||||||
|
r, e = k.parseRequest(query, dns.TypeA, zone)
|
||||||
|
if e != nil {
|
||||||
|
t.Errorf("Expected no error from parseRequest(\"%v\", \"A\"). Instead got '%v'.", query, e)
|
||||||
|
}
|
||||||
|
tcs = map[string]string{
|
||||||
|
"port": "",
|
||||||
|
"protocol": "",
|
||||||
|
"endpoint": "1-2-3-4",
|
||||||
|
"service": "webs",
|
||||||
|
"namespace": "mynamespace",
|
||||||
|
"podOrSvc": Svc,
|
||||||
|
"zone": zone,
|
||||||
|
}
|
||||||
|
for field, expected := range tcs {
|
||||||
|
expectString(t, f, "A", query, &r, field, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test NS request
|
||||||
|
query = "inter.webs.test."
|
||||||
|
r, e = k.parseRequest(query, dns.TypeNS, zone)
|
||||||
|
if e != nil {
|
||||||
|
t.Errorf("Expected no error from parseRequest(\"%v\", \"NS\"). Instead got '%v'.", query, e)
|
||||||
|
}
|
||||||
|
tcs = map[string]string{
|
||||||
|
"port": "",
|
||||||
|
"protocol": "",
|
||||||
|
"endpoint": "",
|
||||||
|
"service": "",
|
||||||
|
"namespace": "",
|
||||||
|
"podOrSvc": "",
|
||||||
|
"zone": zone,
|
||||||
|
}
|
||||||
|
for field, expected := range tcs {
|
||||||
|
expectString(t, f, "NS", query, &r, field, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invalid query tests
|
||||||
|
invalidAQueries := []string{
|
||||||
|
"_http._tcp.webs.mynamespace.svc.inter.webs.test.", // A requests cannot have port or protocol TODO(miek): this must return NODATA
|
||||||
|
|
||||||
|
}
|
||||||
|
for _, q := range invalidAQueries {
|
||||||
|
_, e = k.parseRequest(q, dns.TypeA, zone)
|
||||||
|
if e == nil {
|
||||||
|
t.Errorf("Expected error from %v(\"%v\", \"A\").", f, q)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
invalidSRVQueries := []string{
|
||||||
|
"_http._pcp.webs.mynamespace.svc.inter.webs.test.", // SRV protocol must be tcp or udp
|
||||||
|
"_http._tcp.ep.webs.ns.svc.inter.webs.test.", // SRV requests cannot have an endpoint
|
||||||
|
"_*._*.webs.mynamespace.svc.inter.webs.test.", // SRV request with invalid wildcards
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, q := range invalidSRVQueries {
|
||||||
|
_, e = k.parseRequest(q, dns.TypeSRV, zone)
|
||||||
|
if e == nil {
|
||||||
|
t.Errorf("Expected error from %v(\"%v\", \"SRV\").", f, q)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -555,10 +555,10 @@ func TestKubernetesIntegrationCidrReverseZone(t *testing.T) {
|
||||||
func TestKubernetesIntegrationPartialCidrReverseZone(t *testing.T) {
|
func TestKubernetesIntegrationPartialCidrReverseZone(t *testing.T) {
|
||||||
corefile :=
|
corefile :=
|
||||||
`.:0 {
|
`.:0 {
|
||||||
kubernetes cluster.local {
|
kubernetes cluster.local {
|
||||||
endpoint http://localhost:8080
|
endpoint http://localhost:8080
|
||||||
namespaces test-1
|
namespaces test-1
|
||||||
cidrs 10.0.0.96/28 10.0.0.120/32
|
cidrs 10.0.0.96/28 10.0.0.120/32
|
||||||
}
|
}
|
||||||
erratic . {
|
erratic . {
|
||||||
drop 0
|
drop 0
|
||||||
|
@ -572,7 +572,7 @@ func TestKubernetesIntegrationAllNSExposed(t *testing.T) {
|
||||||
`.:0 {
|
`.:0 {
|
||||||
kubernetes cluster.local {
|
kubernetes cluster.local {
|
||||||
endpoint http://localhost:8080
|
endpoint http://localhost:8080
|
||||||
cidrs 10.0.0.0/24
|
cidrs 10.0.0.0/24
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
doIntegrationTests(t, corefile, dnsTestCasesAllNSExposed)
|
doIntegrationTests(t, corefile, dnsTestCasesAllNSExposed)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue