| 
									
										
										
										
											2018-02-08 10:11:04 -06:00
										 |  |  | package kubernetes
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import (
 | 
					
						
							|  |  |  | 	"strings"
 | 
					
						
							|  |  |  | 	"testing"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/coredns/coredns/plugin/pkg/dnstest"
 | 
					
						
							|  |  |  | 	"github.com/coredns/coredns/plugin/test"
 | 
					
						
							|  |  |  | 	"golang.org/x/net/context"
 | 
					
						
							| 
									
										
										
										
											2018-02-09 17:32:52 -05:00
										 |  |  | 	api "k8s.io/api/core/v1"
 | 
					
						
							|  |  |  | 	meta "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
					
						
							| 
									
										
										
										
											2018-02-08 10:11:04 -06:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/miekg/dns"
 | 
					
						
							|  |  |  | )
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestKubernetesXFR(t *testing.T) {
 | 
					
						
							|  |  |  | 	k := New([]string{"cluster.local."})
 | 
					
						
							|  |  |  | 	k.APIConn = &APIConnServeTest{}
 | 
					
						
							|  |  |  | 	k.TransferTo = []string{"127.0.0.1"}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ctx := context.TODO()
 | 
					
						
							|  |  |  | 	w := dnstest.NewMultiRecorder(&test.ResponseWriter{})
 | 
					
						
							|  |  |  | 	dnsmsg := &dns.Msg{}
 | 
					
						
							|  |  |  | 	dnsmsg.SetAxfr(k.Zones[0])
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	_, err := k.ServeDNS(ctx, w, dnsmsg)
 | 
					
						
							|  |  |  | 	if err != nil {
 | 
					
						
							|  |  |  | 		t.Error(err)
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(w.Msgs) == 0 {
 | 
					
						
							|  |  |  | 		t.Logf("%+v\n", w)
 | 
					
						
							|  |  |  | 		t.Error("Did not get back a zone response")
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Ensure xfr starts with SOA
 | 
					
						
							|  |  |  | 	if w.Msgs[0].Answer[0].Header().Rrtype != dns.TypeSOA {
 | 
					
						
							|  |  |  | 		t.Error("Invalid XFR, does not start with SOA record")
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Ensure xfr starts with SOA
 | 
					
						
							|  |  |  | 	// Last message is empty, so we need to go back one further
 | 
					
						
							|  |  |  | 	if w.Msgs[len(w.Msgs)-2].Answer[len(w.Msgs[len(w.Msgs)-2].Answer)-1].Header().Rrtype != dns.TypeSOA {
 | 
					
						
							|  |  |  | 		t.Error("Invalid XFR, does not end with SOA record")
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	testRRs := []dns.RR{}
 | 
					
						
							|  |  |  | 	for _, tc := range dnsTestCases {
 | 
					
						
							|  |  |  | 		if tc.Rcode != dns.RcodeSuccess {
 | 
					
						
							|  |  |  | 			continue
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for _, ans := range tc.Answer {
 | 
					
						
							|  |  |  | 			// Exclude wildcard searches
 | 
					
						
							|  |  |  | 			if strings.Contains(ans.Header().Name, "*") {
 | 
					
						
							|  |  |  | 				continue
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			// Exclude TXT records
 | 
					
						
							|  |  |  | 			if ans.Header().Rrtype == dns.TypeTXT {
 | 
					
						
							|  |  |  | 				continue
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 			testRRs = append(testRRs, ans)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	gotRRs := []dns.RR{}
 | 
					
						
							|  |  |  | 	for _, resp := range w.Msgs {
 | 
					
						
							|  |  |  | 		for _, ans := range resp.Answer {
 | 
					
						
							|  |  |  | 			// Skip SOA records since these
 | 
					
						
							|  |  |  | 			// test cases do not exist
 | 
					
						
							|  |  |  | 			if ans.Header().Rrtype == dns.TypeSOA {
 | 
					
						
							|  |  |  | 				continue
 | 
					
						
							|  |  |  | 			}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			gotRRs = append(gotRRs, ans)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	diff := difference(testRRs, gotRRs)
 | 
					
						
							|  |  |  | 	if len(diff) != 0 {
 | 
					
						
							|  |  |  | 		t.Errorf("Got back %d records that do not exist in test cases, should be 0:", len(diff))
 | 
					
						
							|  |  |  | 		for _, rec := range diff {
 | 
					
						
							|  |  |  | 			t.Errorf("%+v", rec)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	diff = difference(gotRRs, testRRs)
 | 
					
						
							|  |  |  | 	if len(diff) != 0 {
 | 
					
						
							|  |  |  | 		t.Errorf("Found %d records we're missing tham test cases, should be 0:", len(diff))
 | 
					
						
							|  |  |  | 		for _, rec := range diff {
 | 
					
						
							|  |  |  | 			t.Errorf("%+v", rec)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | }
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // difference shows what we're missing when comparing two RR slices
 | 
					
						
							|  |  |  | func difference(testRRs []dns.RR, gotRRs []dns.RR) []dns.RR {
 | 
					
						
							|  |  |  | 	expectedRRs := map[string]bool{}
 | 
					
						
							|  |  |  | 	for _, rr := range testRRs {
 | 
					
						
							|  |  |  | 		expectedRRs[rr.String()] = true
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	foundRRs := []dns.RR{}
 | 
					
						
							|  |  |  | 	for _, rr := range gotRRs {
 | 
					
						
							|  |  |  | 		if _, ok := expectedRRs[rr.String()]; !ok {
 | 
					
						
							|  |  |  | 			foundRRs = append(foundRRs, rr)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	return foundRRs
 | 
					
						
							|  |  |  | }
 | 
					
						
							| 
									
										
										
										
											2018-02-09 17:32:52 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestEndpointsEquivalent(t *testing.T) {
 | 
					
						
							|  |  |  | 	epA := api.Endpoints{
 | 
					
						
							|  |  |  | 		ObjectMeta: meta.ObjectMeta{ResourceVersion: "1230"},
 | 
					
						
							|  |  |  | 		Subsets: []api.EndpointSubset{{
 | 
					
						
							|  |  |  | 			Addresses:         []api.EndpointAddress{{IP: "1.2.3.4", Hostname: "foo"}},
 | 
					
						
							|  |  |  | 			NotReadyAddresses: []api.EndpointAddress{{IP: "1.2.3.5", Hostname: "foobar"}},
 | 
					
						
							|  |  |  | 		}},
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	epB := api.Endpoints{
 | 
					
						
							|  |  |  | 		ObjectMeta: meta.ObjectMeta{ResourceVersion: "1234"},
 | 
					
						
							|  |  |  | 		Subsets: []api.EndpointSubset{{
 | 
					
						
							|  |  |  | 			Addresses:         []api.EndpointAddress{{IP: "1.2.3.4", Hostname: "foo"}},
 | 
					
						
							|  |  |  | 			NotReadyAddresses: []api.EndpointAddress{{IP: "1.1.1.1", Hostname: "foobar"}},
 | 
					
						
							|  |  |  | 		}},
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	epC := api.Endpoints{
 | 
					
						
							|  |  |  | 		Subsets: []api.EndpointSubset{{
 | 
					
						
							|  |  |  | 			Addresses: []api.EndpointAddress{{IP: "1.2.3.5", Hostname: "foo"}},
 | 
					
						
							|  |  |  | 		}},
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	epD := api.Endpoints{
 | 
					
						
							|  |  |  | 		Subsets: []api.EndpointSubset{{
 | 
					
						
							|  |  |  | 			Addresses: []api.EndpointAddress{{IP: "1.2.3.5", Hostname: "foo"}},
 | 
					
						
							|  |  |  | 		},
 | 
					
						
							|  |  |  | 			{
 | 
					
						
							|  |  |  | 				Addresses: []api.EndpointAddress{{IP: "1.2.2.2", Hostname: "foofoo"}},
 | 
					
						
							|  |  |  | 			}},
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	epE := api.Endpoints{
 | 
					
						
							|  |  |  | 		Subsets: []api.EndpointSubset{{
 | 
					
						
							|  |  |  | 			Addresses: []api.EndpointAddress{{IP: "1.2.3.5", Hostname: "foo"}, {IP: "1.1.1.1"}},
 | 
					
						
							|  |  |  | 		}},
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	epF := api.Endpoints{
 | 
					
						
							|  |  |  | 		Subsets: []api.EndpointSubset{{
 | 
					
						
							|  |  |  | 			Addresses: []api.EndpointAddress{{IP: "1.2.3.4", Hostname: "foofoo"}},
 | 
					
						
							|  |  |  | 		}},
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	epG := api.Endpoints{
 | 
					
						
							|  |  |  | 		Subsets: []api.EndpointSubset{{
 | 
					
						
							|  |  |  | 			Addresses: []api.EndpointAddress{{IP: "1.2.3.4", Hostname: "foo"}},
 | 
					
						
							|  |  |  | 			Ports:     []api.EndpointPort{{Name: "http", Port: 80, Protocol: "TCP"}},
 | 
					
						
							|  |  |  | 		}},
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	epH := api.Endpoints{
 | 
					
						
							|  |  |  | 		Subsets: []api.EndpointSubset{{
 | 
					
						
							|  |  |  | 			Addresses: []api.EndpointAddress{{IP: "1.2.3.4", Hostname: "foo"}},
 | 
					
						
							|  |  |  | 			Ports:     []api.EndpointPort{{Name: "newportname", Port: 80, Protocol: "TCP"}},
 | 
					
						
							|  |  |  | 		}},
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	epI := api.Endpoints{
 | 
					
						
							|  |  |  | 		Subsets: []api.EndpointSubset{{
 | 
					
						
							|  |  |  | 			Addresses: []api.EndpointAddress{{IP: "1.2.3.4", Hostname: "foo"}},
 | 
					
						
							|  |  |  | 			Ports:     []api.EndpointPort{{Name: "http", Port: 8080, Protocol: "TCP"}},
 | 
					
						
							|  |  |  | 		}},
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 	epJ := api.Endpoints{
 | 
					
						
							|  |  |  | 		Subsets: []api.EndpointSubset{{
 | 
					
						
							|  |  |  | 			Addresses: []api.EndpointAddress{{IP: "1.2.3.4", Hostname: "foo"}},
 | 
					
						
							|  |  |  | 			Ports:     []api.EndpointPort{{Name: "http", Port: 80, Protocol: "UDP"}},
 | 
					
						
							|  |  |  | 		}},
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tests := []struct {
 | 
					
						
							|  |  |  | 		equiv bool
 | 
					
						
							|  |  |  | 		a     *api.Endpoints
 | 
					
						
							|  |  |  | 		b     *api.Endpoints
 | 
					
						
							|  |  |  | 	}{
 | 
					
						
							|  |  |  | 		{true, &epA, &epB},
 | 
					
						
							|  |  |  | 		{false, &epA, &epC},
 | 
					
						
							|  |  |  | 		{false, &epA, &epD},
 | 
					
						
							|  |  |  | 		{false, &epA, &epE},
 | 
					
						
							|  |  |  | 		{false, &epA, &epF},
 | 
					
						
							|  |  |  | 		{false, &epF, &epG},
 | 
					
						
							|  |  |  | 		{false, &epG, &epH},
 | 
					
						
							|  |  |  | 		{false, &epG, &epI},
 | 
					
						
							|  |  |  | 		{false, &epG, &epJ},
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i, tc := range tests {
 | 
					
						
							|  |  |  | 		if tc.equiv && !endpointsEquivalent(tc.a, tc.b) {
 | 
					
						
							|  |  |  | 			t.Errorf("Test %d: expected endpoints to be equivalent and they are not.", i)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 		if !tc.equiv && endpointsEquivalent(tc.a, tc.b) {
 | 
					
						
							|  |  |  | 			t.Errorf("Test %d: expected endpoints to be seen as different but they were not.", i)
 | 
					
						
							|  |  |  | 		}
 | 
					
						
							|  |  |  | 	}
 | 
					
						
							|  |  |  | }
 |