dns_test.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. /*
  2. Copyright 2016 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package dns
  14. import (
  15. "encoding/json"
  16. "fmt"
  17. "net"
  18. "strings"
  19. "sync"
  20. "testing"
  21. etcd "github.com/coreos/etcd/client"
  22. "github.com/miekg/dns"
  23. skymsg "github.com/skynetservices/skydns/msg"
  24. skyServer "github.com/skynetservices/skydns/server"
  25. "github.com/stretchr/testify/assert"
  26. "github.com/stretchr/testify/require"
  27. kapi "k8s.io/kubernetes/pkg/api"
  28. endpointsapi "k8s.io/kubernetes/pkg/api/endpoints"
  29. "k8s.io/kubernetes/pkg/api/unversioned"
  30. "k8s.io/kubernetes/pkg/client/cache"
  31. fake "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/fake"
  32. "k8s.io/kubernetes/pkg/util/sets"
  33. )
  34. const (
  35. testDomain = "cluster.local."
  36. testService = "testservice"
  37. testNamespace = "default"
  38. testExternalName = "foo.bar.example.com"
  39. )
  40. func newKubeDNS() *KubeDNS {
  41. kd := &KubeDNS{
  42. domain: testDomain,
  43. endpointsStore: cache.NewStore(cache.MetaNamespaceKeyFunc),
  44. servicesStore: cache.NewStore(cache.MetaNamespaceKeyFunc),
  45. cache: NewTreeCache(),
  46. reverseRecordMap: make(map[string]*skymsg.Service),
  47. clusterIPServiceMap: make(map[string]*kapi.Service),
  48. cacheLock: sync.RWMutex{},
  49. domainPath: reverseArray(strings.Split(strings.TrimRight(testDomain, "."), ".")),
  50. nodesStore: cache.NewStore(cache.MetaNamespaceKeyFunc),
  51. }
  52. return kd
  53. }
  54. func TestNewKubeDNS(t *testing.T) {
  55. // Verify that it returns an error for invalid federation names.
  56. _, err := NewKubeDNS(nil, "domainName", map[string]string{"invalid.name.with.dot": "example.come"})
  57. if err == nil {
  58. t.Errorf("Expected an error due to invalid federation name")
  59. }
  60. }
  61. func TestPodDns(t *testing.T) {
  62. const (
  63. testPodIP = "1.2.3.4"
  64. sanitizedPodIP = "1-2-3-4"
  65. )
  66. kd := newKubeDNS()
  67. records, err := kd.Records(sanitizedPodIP+".default.pod."+kd.domain, false)
  68. require.NoError(t, err)
  69. assert.Equal(t, 1, len(records))
  70. assert.Equal(t, testPodIP, records[0].Host)
  71. }
  72. func TestUnnamedSinglePortService(t *testing.T) {
  73. kd := newKubeDNS()
  74. s := newService(testNamespace, testService, "1.2.3.4", "", 80)
  75. // Add the service
  76. kd.newService(s)
  77. assertDNSForClusterIP(t, kd, s)
  78. assertReverseRecord(t, kd, s)
  79. // Delete the service
  80. kd.removeService(s)
  81. assertNoDNSForClusterIP(t, kd, s)
  82. assertNoReverseRecord(t, kd, s)
  83. }
  84. func TestNamedSinglePortService(t *testing.T) {
  85. const (
  86. portName1 = "http1"
  87. portName2 = "http2"
  88. )
  89. kd := newKubeDNS()
  90. s := newService(testNamespace, testService, "1.2.3.4", portName1, 80)
  91. // Add the service
  92. kd.newService(s)
  93. assertDNSForClusterIP(t, kd, s)
  94. assertSRVForNamedPort(t, kd, s, portName1)
  95. newService := *s
  96. // update the portName of the service
  97. newService.Spec.Ports[0].Name = portName2
  98. kd.updateService(s, &newService)
  99. assertDNSForClusterIP(t, kd, s)
  100. assertSRVForNamedPort(t, kd, s, portName2)
  101. assertNoSRVForNamedPort(t, kd, s, portName1)
  102. // Delete the service
  103. kd.removeService(s)
  104. assertNoDNSForClusterIP(t, kd, s)
  105. assertNoSRVForNamedPort(t, kd, s, portName1)
  106. assertNoSRVForNamedPort(t, kd, s, portName2)
  107. }
  108. func assertARecordsMatchIPs(t *testing.T, records []dns.RR, ips ...string) {
  109. expectedEndpoints := sets.NewString(ips...)
  110. gotEndpoints := sets.NewString()
  111. for _, r := range records {
  112. if a, ok := r.(*dns.A); !ok {
  113. t.Errorf("Expected A record, got %#v", a)
  114. } else {
  115. gotEndpoints.Insert(a.A.String())
  116. }
  117. }
  118. if !gotEndpoints.Equal(expectedEndpoints) {
  119. t.Errorf("Expected %v got %v", expectedEndpoints, gotEndpoints)
  120. }
  121. }
  122. func assertSRVRecordsMatchTarget(t *testing.T, records []dns.RR, targets ...string) {
  123. expectedTargets := sets.NewString(targets...)
  124. gotTargets := sets.NewString()
  125. for _, r := range records {
  126. if srv, ok := r.(*dns.SRV); !ok {
  127. t.Errorf("Expected SRV record, got %+v", srv)
  128. } else {
  129. gotTargets.Insert(srv.Target)
  130. }
  131. }
  132. if !gotTargets.Equal(expectedTargets) {
  133. t.Errorf("Expected %v got %v", expectedTargets, gotTargets)
  134. }
  135. }
  136. func assertSRVRecordsMatchPort(t *testing.T, records []dns.RR, port ...int) {
  137. expectedPorts := sets.NewInt(port...)
  138. gotPorts := sets.NewInt()
  139. for _, r := range records {
  140. if srv, ok := r.(*dns.SRV); !ok {
  141. t.Errorf("Expected SRV record, got %+v", srv)
  142. } else {
  143. gotPorts.Insert(int(srv.Port))
  144. t.Logf("got %+v", srv)
  145. }
  146. }
  147. if !gotPorts.Equal(expectedPorts) {
  148. t.Errorf("Expected %v got %v", expectedPorts, gotPorts)
  149. }
  150. }
  151. func TestSkySimpleSRVLookup(t *testing.T) {
  152. kd := newKubeDNS()
  153. skydnsConfig := &skyServer.Config{Domain: testDomain, DnsAddr: "0.0.0.0:53"}
  154. skyServer.SetDefaults(skydnsConfig)
  155. s := skyServer.New(kd, skydnsConfig)
  156. service := newHeadlessService()
  157. endpointIPs := []string{"10.0.0.1", "10.0.0.2"}
  158. endpoints := newEndpoints(service, newSubsetWithOnePort("", 80, endpointIPs...))
  159. assert.NoError(t, kd.endpointsStore.Add(endpoints))
  160. kd.newService(service)
  161. name := strings.Join([]string{testService, testNamespace, "svc", testDomain}, ".")
  162. question := dns.Question{Name: name, Qtype: dns.TypeSRV, Qclass: dns.ClassINET}
  163. rec, extra, err := s.SRVRecords(question, name, 512, false)
  164. if err != nil {
  165. t.Fatalf("Failed srv record lookup on service with fqdn %v", name)
  166. }
  167. assertARecordsMatchIPs(t, extra, endpointIPs...)
  168. targets := []string{}
  169. for _, eip := range endpointIPs {
  170. // A portal service is always created with a port of '0'
  171. targets = append(targets, fmt.Sprintf("%v.%v", fmt.Sprintf("%x", hashServiceRecord(newServiceRecord(eip, 0))), name))
  172. }
  173. assertSRVRecordsMatchTarget(t, rec, targets...)
  174. }
  175. func TestSkyPodHostnameSRVLookup(t *testing.T) {
  176. kd := newKubeDNS()
  177. skydnsConfig := &skyServer.Config{Domain: testDomain, DnsAddr: "0.0.0.0:53"}
  178. skyServer.SetDefaults(skydnsConfig)
  179. s := skyServer.New(kd, skydnsConfig)
  180. service := newHeadlessService()
  181. endpointIPs := []string{"10.0.0.1", "10.0.0.2"}
  182. endpoints := newEndpoints(service, newSubsetWithOnePort("", 80, endpointIPs...))
  183. // The format of thes annotations is:
  184. // endpoints.beta.kubernetes.io/hostnames-map: '{"ep-ip":{"HostName":"pod request hostname"}}'
  185. epRecords := map[string]endpointsapi.HostRecord{}
  186. for i, ep := range endpointIPs {
  187. epRecords[ep] = endpointsapi.HostRecord{HostName: fmt.Sprintf("ep-%d", i)}
  188. }
  189. b, err := json.Marshal(epRecords)
  190. if err != nil {
  191. t.Fatalf("%v", err)
  192. }
  193. endpoints.Annotations = map[string]string{
  194. endpointsapi.PodHostnamesAnnotation: string(b),
  195. }
  196. assert.NoError(t, kd.endpointsStore.Add(endpoints))
  197. kd.newService(service)
  198. name := strings.Join([]string{testService, testNamespace, "svc", testDomain}, ".")
  199. question := dns.Question{Name: name, Qtype: dns.TypeSRV, Qclass: dns.ClassINET}
  200. rec, _, err := s.SRVRecords(question, name, 512, false)
  201. if err != nil {
  202. t.Fatalf("Failed srv record lookup on service with fqdn %v", name)
  203. }
  204. targets := []string{}
  205. for i := range endpointIPs {
  206. targets = append(targets, fmt.Sprintf("%v.%v", fmt.Sprintf("ep-%d", i), name))
  207. }
  208. assertSRVRecordsMatchTarget(t, rec, targets...)
  209. }
  210. func TestSkyNamedPortSRVLookup(t *testing.T) {
  211. kd := newKubeDNS()
  212. skydnsConfig := &skyServer.Config{Domain: testDomain, DnsAddr: "0.0.0.0:53"}
  213. skyServer.SetDefaults(skydnsConfig)
  214. s := skyServer.New(kd, skydnsConfig)
  215. service := newHeadlessService()
  216. eip := "10.0.0.1"
  217. endpoints := newEndpoints(service, newSubsetWithOnePort("http", 8081, eip))
  218. assert.NoError(t, kd.endpointsStore.Add(endpoints))
  219. kd.newService(service)
  220. name := strings.Join([]string{"_http", "_tcp", testService, testNamespace, "svc", testDomain}, ".")
  221. question := dns.Question{Name: name, Qtype: dns.TypeSRV, Qclass: dns.ClassINET}
  222. rec, extra, err := s.SRVRecords(question, name, 512, false)
  223. if err != nil {
  224. t.Fatalf("Failed srv record lookup on service with fqdn %v", name)
  225. }
  226. svcDomain := strings.Join([]string{testService, testNamespace, "svc", testDomain}, ".")
  227. assertARecordsMatchIPs(t, extra, eip)
  228. assertSRVRecordsMatchTarget(t, rec, fmt.Sprintf("%v.%v", fmt.Sprintf("%x", hashServiceRecord(newServiceRecord(eip, 0))), svcDomain))
  229. assertSRVRecordsMatchPort(t, rec, 8081)
  230. }
  231. func TestSimpleExternalService(t *testing.T) {
  232. kd := newKubeDNS()
  233. s := newExternalNameService()
  234. assert.NoError(t, kd.servicesStore.Add(s))
  235. kd.newService(s)
  236. assertDNSForExternalService(t, kd, s)
  237. kd.removeService(s)
  238. assertNoDNSForExternalService(t, kd, s)
  239. }
  240. func TestSimpleHeadlessService(t *testing.T) {
  241. kd := newKubeDNS()
  242. s := newHeadlessService()
  243. assert.NoError(t, kd.servicesStore.Add(s))
  244. endpoints := newEndpoints(s, newSubsetWithOnePort("", 80, "10.0.0.1", "10.0.0.2"), newSubsetWithOnePort("", 8080, "10.0.0.3", "10.0.0.4"))
  245. assert.NoError(t, kd.endpointsStore.Add(endpoints))
  246. kd.newService(s)
  247. assertDNSForHeadlessService(t, kd, endpoints)
  248. kd.removeService(s)
  249. assertNoDNSForHeadlessService(t, kd, s)
  250. }
  251. func TestHeadlessServiceWithNamedPorts(t *testing.T) {
  252. kd := newKubeDNS()
  253. service := newHeadlessService()
  254. // add service to store
  255. assert.NoError(t, kd.servicesStore.Add(service))
  256. endpoints := newEndpoints(service, newSubsetWithTwoPorts("http1", 80, "http2", 81, "10.0.0.1", "10.0.0.2"),
  257. newSubsetWithOnePort("https", 443, "10.0.0.3", "10.0.0.4"))
  258. // We expect 10 records. 6 SRV records. 4 POD records.
  259. // add endpoints
  260. assert.NoError(t, kd.endpointsStore.Add(endpoints))
  261. // add service
  262. kd.newService(service)
  263. assertDNSForHeadlessService(t, kd, endpoints)
  264. assertSRVForHeadlessService(t, kd, service, endpoints)
  265. // reduce endpoints
  266. endpoints.Subsets = endpoints.Subsets[:1]
  267. kd.handleEndpointAdd(endpoints)
  268. // We expect 6 records. 4 SRV records. 2 POD records.
  269. assertDNSForHeadlessService(t, kd, endpoints)
  270. assertSRVForHeadlessService(t, kd, service, endpoints)
  271. kd.removeService(service)
  272. assertNoDNSForHeadlessService(t, kd, service)
  273. }
  274. func TestHeadlessServiceEndpointsUpdate(t *testing.T) {
  275. kd := newKubeDNS()
  276. service := newHeadlessService()
  277. // add service to store
  278. assert.NoError(t, kd.servicesStore.Add(service))
  279. endpoints := newEndpoints(service, newSubsetWithOnePort("", 80, "10.0.0.1", "10.0.0.2"))
  280. // add endpoints to store
  281. assert.NoError(t, kd.endpointsStore.Add(endpoints))
  282. // add service
  283. kd.newService(service)
  284. assertDNSForHeadlessService(t, kd, endpoints)
  285. // increase endpoints
  286. endpoints.Subsets = append(endpoints.Subsets,
  287. newSubsetWithOnePort("", 8080, "10.0.0.3", "10.0.0.4"),
  288. )
  289. // expected DNSRecords = 4
  290. kd.handleEndpointAdd(endpoints)
  291. assertDNSForHeadlessService(t, kd, endpoints)
  292. // remove all endpoints
  293. endpoints.Subsets = []kapi.EndpointSubset{}
  294. kd.handleEndpointAdd(endpoints)
  295. assertNoDNSForHeadlessService(t, kd, service)
  296. // remove service
  297. kd.removeService(service)
  298. assertNoDNSForHeadlessService(t, kd, service)
  299. }
  300. func TestHeadlessServiceWithDelayedEndpointsAddition(t *testing.T) {
  301. kd := newKubeDNS()
  302. // create service
  303. service := newHeadlessService()
  304. // add service to store
  305. assert.NoError(t, kd.servicesStore.Add(service))
  306. // add service
  307. kd.newService(service)
  308. assertNoDNSForHeadlessService(t, kd, service)
  309. // create endpoints
  310. endpoints := newEndpoints(service, newSubsetWithOnePort("", 80, "10.0.0.1", "10.0.0.2"))
  311. // add endpoints to store
  312. assert.NoError(t, kd.endpointsStore.Add(endpoints))
  313. // add endpoints
  314. kd.handleEndpointAdd(endpoints)
  315. assertDNSForHeadlessService(t, kd, endpoints)
  316. // remove service
  317. kd.removeService(service)
  318. assertNoDNSForHeadlessService(t, kd, service)
  319. }
  320. // Verifies that a single record with host "a" is returned for query "q".
  321. func verifyRecord(q, a string, t *testing.T, kd *KubeDNS) {
  322. records, err := kd.Records(q, false)
  323. require.NoError(t, err)
  324. assert.Equal(t, 1, len(records))
  325. assert.Equal(t, a, records[0].Host)
  326. }
  327. // Verifies that quering KubeDNS for a headless federation service returns the DNS hostname when a local service does not exist and returns the endpoint IP when a local service exists.
  328. func TestFederationHeadlessService(t *testing.T) {
  329. kd := newKubeDNS()
  330. kd.federations = map[string]string{
  331. "myfederation": "example.com",
  332. }
  333. kd.kubeClient = fake.NewSimpleClientset(newNodes())
  334. // Verify that quering for federation service returns a federation domain name.
  335. verifyRecord("testservice.default.myfederation.svc.cluster.local.",
  336. "testservice.default.myfederation.svc.testcontinent-testreg-testzone.testcontinent-testreg.example.com.",
  337. t, kd)
  338. // Add a local service without any endpoint.
  339. s := newHeadlessService()
  340. assert.NoError(t, kd.servicesStore.Add(s))
  341. kd.newService(s)
  342. // Verify that quering for federation service still returns the federation domain name.
  343. verifyRecord(getFederationServiceFQDN(kd, s, "myfederation"),
  344. "testservice.default.myfederation.svc.testcontinent-testreg-testzone.testcontinent-testreg.example.com.",
  345. t, kd)
  346. // Now add an endpoint.
  347. endpoints := newEndpoints(s, newSubsetWithOnePort("", 80, "10.0.0.1"))
  348. assert.NoError(t, kd.endpointsStore.Add(endpoints))
  349. kd.updateService(s, s)
  350. // Verify that quering for federation service returns the local service domain name this time.
  351. verifyRecord(getFederationServiceFQDN(kd, s, "myfederation"), "testservice.default.svc.cluster.local.", t, kd)
  352. // Delete the endpoint.
  353. endpoints.Subsets = []kapi.EndpointSubset{}
  354. kd.handleEndpointAdd(endpoints)
  355. kd.updateService(s, s)
  356. // Verify that quering for federation service returns the federation domain name again.
  357. verifyRecord(getFederationServiceFQDN(kd, s, "myfederation"),
  358. "testservice.default.myfederation.svc.testcontinent-testreg-testzone.testcontinent-testreg.example.com.",
  359. t, kd)
  360. }
  361. // Verifies that quering KubeDNS for a federation service returns the DNS hostname if no endpoint exists and returns the local cluster IP if endpoints exist.
  362. func TestFederationService(t *testing.T) {
  363. kd := newKubeDNS()
  364. kd.federations = map[string]string{
  365. "myfederation": "example.com",
  366. }
  367. kd.kubeClient = fake.NewSimpleClientset(newNodes())
  368. // Verify that quering for federation service returns the federation domain name.
  369. verifyRecord("testservice.default.myfederation.svc.cluster.local.",
  370. "testservice.default.myfederation.svc.testcontinent-testreg-testzone.testcontinent-testreg.example.com.",
  371. t, kd)
  372. // Add a local service without any endpoint.
  373. s := newService(testNamespace, testService, "1.2.3.4", "", 80)
  374. assert.NoError(t, kd.servicesStore.Add(s))
  375. kd.newService(s)
  376. // Verify that quering for federation service still returns the federation domain name.
  377. verifyRecord(getFederationServiceFQDN(kd, s, "myfederation"),
  378. "testservice.default.myfederation.svc.testcontinent-testreg-testzone.testcontinent-testreg.example.com.",
  379. t, kd)
  380. // Now add an endpoint.
  381. endpoints := newEndpoints(s, newSubsetWithOnePort("", 80, "10.0.0.1"))
  382. assert.NoError(t, kd.endpointsStore.Add(endpoints))
  383. kd.updateService(s, s)
  384. // Verify that quering for federation service returns the local service domain name this time.
  385. verifyRecord(getFederationServiceFQDN(kd, s, "myfederation"), "testservice.default.svc.cluster.local.", t, kd)
  386. // Remove the endpoint.
  387. endpoints.Subsets = []kapi.EndpointSubset{}
  388. kd.handleEndpointAdd(endpoints)
  389. kd.updateService(s, s)
  390. // Verify that quering for federation service returns the federation domain name again.
  391. verifyRecord(getFederationServiceFQDN(kd, s, "myfederation"),
  392. "testservice.default.myfederation.svc.testcontinent-testreg-testzone.testcontinent-testreg.example.com.",
  393. t, kd)
  394. }
  395. func TestFederationQueryWithoutCache(t *testing.T) {
  396. kd := newKubeDNS()
  397. kd.federations = map[string]string{
  398. "myfederation": "example.com",
  399. "secondfederation": "second.example.com",
  400. }
  401. kd.kubeClient = fake.NewSimpleClientset(newNodes())
  402. testValidFederationQueries(t, kd)
  403. testInvalidFederationQueries(t, kd)
  404. }
  405. func TestFederationQueryWithCache(t *testing.T) {
  406. kd := newKubeDNS()
  407. kd.federations = map[string]string{
  408. "myfederation": "example.com",
  409. "secondfederation": "second.example.com",
  410. }
  411. // Add a node to the cache.
  412. nodeList := newNodes()
  413. if err := kd.nodesStore.Add(&nodeList.Items[1]); err != nil {
  414. t.Errorf("failed to add the node to the cache: %v", err)
  415. }
  416. testValidFederationQueries(t, kd)
  417. testInvalidFederationQueries(t, kd)
  418. }
  419. func testValidFederationQueries(t *testing.T, kd *KubeDNS) {
  420. queries := []struct {
  421. q string
  422. a string
  423. }{
  424. // Federation suffix is just a domain.
  425. {
  426. q: "mysvc.myns.myfederation.svc.cluster.local.",
  427. a: "mysvc.myns.myfederation.svc.testcontinent-testreg-testzone.testcontinent-testreg.example.com.",
  428. },
  429. // Federation suffix is a subdomain.
  430. {
  431. q: "secsvc.default.secondfederation.svc.cluster.local.",
  432. a: "secsvc.default.secondfederation.svc.testcontinent-testreg-testzone.testcontinent-testreg.second.example.com.",
  433. },
  434. }
  435. for _, query := range queries {
  436. verifyRecord(query.q, query.a, t, kd)
  437. }
  438. }
  439. func testInvalidFederationQueries(t *testing.T, kd *KubeDNS) {
  440. noAnswerQueries := []string{
  441. "mysvc.myns.svc.cluster.local.",
  442. "mysvc.default.nofederation.svc.cluster.local.",
  443. }
  444. for _, q := range noAnswerQueries {
  445. records, err := kd.Records(q, false)
  446. if err == nil {
  447. t.Errorf("expected not found error, got nil")
  448. }
  449. if etcdErr, ok := err.(etcd.Error); !ok || etcdErr.Code != etcd.ErrorCodeKeyNotFound {
  450. t.Errorf("expected not found error, got %v", etcdErr)
  451. }
  452. assert.Equal(t, 0, len(records))
  453. }
  454. }
  455. func newNodes() *kapi.NodeList {
  456. return &kapi.NodeList{
  457. Items: []kapi.Node{
  458. // Node without annotation.
  459. {
  460. ObjectMeta: kapi.ObjectMeta{
  461. Name: "testnode-0",
  462. },
  463. },
  464. {
  465. ObjectMeta: kapi.ObjectMeta{
  466. Name: "testnode-1",
  467. Labels: map[string]string{
  468. // Note: The zone name here is an arbitrary string and doesn't exactly follow the
  469. // format used by the cloud providers to name their zones. But that shouldn't matter
  470. // for these tests here.
  471. unversioned.LabelZoneFailureDomain: "testcontinent-testreg-testzone",
  472. unversioned.LabelZoneRegion: "testcontinent-testreg",
  473. },
  474. },
  475. },
  476. },
  477. }
  478. }
  479. func newService(namespace, serviceName, clusterIP, portName string, portNumber int32) *kapi.Service {
  480. service := kapi.Service{
  481. ObjectMeta: kapi.ObjectMeta{
  482. Name: serviceName,
  483. Namespace: namespace,
  484. },
  485. Spec: kapi.ServiceSpec{
  486. ClusterIP: clusterIP,
  487. Ports: []kapi.ServicePort{
  488. {Port: portNumber, Name: portName, Protocol: "TCP"},
  489. },
  490. },
  491. }
  492. return &service
  493. }
  494. func newExternalNameService() *kapi.Service {
  495. service := kapi.Service{
  496. ObjectMeta: kapi.ObjectMeta{
  497. Name: testService,
  498. Namespace: testNamespace,
  499. },
  500. Spec: kapi.ServiceSpec{
  501. ClusterIP: "None",
  502. Type: kapi.ServiceTypeExternalName,
  503. ExternalName: testExternalName,
  504. Ports: []kapi.ServicePort{
  505. {Port: 0},
  506. },
  507. },
  508. }
  509. return &service
  510. }
  511. func newHeadlessService() *kapi.Service {
  512. service := kapi.Service{
  513. ObjectMeta: kapi.ObjectMeta{
  514. Name: testService,
  515. Namespace: testNamespace,
  516. },
  517. Spec: kapi.ServiceSpec{
  518. ClusterIP: "None",
  519. Ports: []kapi.ServicePort{
  520. {Port: 0},
  521. },
  522. },
  523. }
  524. return &service
  525. }
  526. func newEndpoints(service *kapi.Service, subsets ...kapi.EndpointSubset) *kapi.Endpoints {
  527. endpoints := kapi.Endpoints{
  528. ObjectMeta: service.ObjectMeta,
  529. Subsets: []kapi.EndpointSubset{},
  530. }
  531. endpoints.Subsets = append(endpoints.Subsets, subsets...)
  532. return &endpoints
  533. }
  534. func newSubsetWithOnePort(portName string, port int32, ips ...string) kapi.EndpointSubset {
  535. subset := newSubset()
  536. subset.Ports = append(subset.Ports, kapi.EndpointPort{Port: port, Name: portName, Protocol: "TCP"})
  537. for _, ip := range ips {
  538. subset.Addresses = append(subset.Addresses, kapi.EndpointAddress{IP: ip})
  539. }
  540. return subset
  541. }
  542. func newSubsetWithTwoPorts(portName1 string, portNumber1 int32, portName2 string, portNumber2 int32, ips ...string) kapi.EndpointSubset {
  543. subset := newSubsetWithOnePort(portName1, portNumber1, ips...)
  544. subset.Ports = append(subset.Ports, kapi.EndpointPort{Port: portNumber2, Name: portName2, Protocol: "TCP"})
  545. return subset
  546. }
  547. func newSubset() kapi.EndpointSubset {
  548. subset := kapi.EndpointSubset{
  549. Addresses: []kapi.EndpointAddress{},
  550. Ports: []kapi.EndpointPort{},
  551. }
  552. return subset
  553. }
  554. func assertSRVForHeadlessService(t *testing.T, kd *KubeDNS, s *kapi.Service, e *kapi.Endpoints) {
  555. for _, subset := range e.Subsets {
  556. for _, port := range subset.Ports {
  557. records, err := kd.Records(getSRVFQDN(kd, s, port.Name), false)
  558. require.NoError(t, err)
  559. assertRecordPortsMatchPort(t, port.Port, records)
  560. assertCNameRecordsMatchEndpointIPs(t, kd, subset.Addresses, records)
  561. }
  562. }
  563. }
  564. func assertDNSForHeadlessService(t *testing.T, kd *KubeDNS, e *kapi.Endpoints) {
  565. records, err := kd.Records(getEndpointsFQDN(kd, e), false)
  566. require.NoError(t, err)
  567. endpoints := map[string]bool{}
  568. for _, subset := range e.Subsets {
  569. for _, endpointAddress := range subset.Addresses {
  570. endpoints[endpointAddress.IP] = true
  571. }
  572. }
  573. assert.Equal(t, len(endpoints), len(records))
  574. for _, record := range records {
  575. _, found := endpoints[record.Host]
  576. assert.True(t, found)
  577. }
  578. }
  579. func assertDNSForExternalService(t *testing.T, kd *KubeDNS, s *kapi.Service) {
  580. records, err := kd.Records(getServiceFQDN(kd, s), false)
  581. require.NoError(t, err)
  582. assert.Equal(t, 1, len(records))
  583. assert.Equal(t, testExternalName, records[0].Host)
  584. }
  585. func assertRecordPortsMatchPort(t *testing.T, port int32, records []skymsg.Service) {
  586. for _, record := range records {
  587. assert.Equal(t, port, int32(record.Port))
  588. }
  589. }
  590. func assertCNameRecordsMatchEndpointIPs(t *testing.T, kd *KubeDNS, e []kapi.EndpointAddress, records []skymsg.Service) {
  591. endpoints := map[string]bool{}
  592. for _, endpointAddress := range e {
  593. endpoints[endpointAddress.IP] = true
  594. }
  595. assert.Equal(t, len(e), len(records), "unexpected record count")
  596. for _, record := range records {
  597. _, found := endpoints[getIPForCName(t, kd, record.Host)]
  598. assert.True(t, found, "Did not find endpoint with address:%s", record.Host)
  599. }
  600. }
  601. func getIPForCName(t *testing.T, kd *KubeDNS, cname string) string {
  602. records, err := kd.Records(cname, false)
  603. require.NoError(t, err)
  604. assert.Equal(t, 1, len(records), "Could not get IP for CNAME record for %s", cname)
  605. assert.NotNil(t, net.ParseIP(records[0].Host), "Invalid IP address %q", records[0].Host)
  606. return records[0].Host
  607. }
  608. func assertNoDNSForHeadlessService(t *testing.T, kd *KubeDNS, s *kapi.Service) {
  609. records, err := kd.Records(getServiceFQDN(kd, s), false)
  610. require.Error(t, err)
  611. assert.Equal(t, 0, len(records))
  612. }
  613. func assertNoDNSForExternalService(t *testing.T, kd *KubeDNS, s *kapi.Service) {
  614. records, err := kd.Records(getServiceFQDN(kd, s), false)
  615. require.Error(t, err)
  616. assert.Equal(t, 0, len(records))
  617. }
  618. func assertSRVForNamedPort(t *testing.T, kd *KubeDNS, s *kapi.Service, portName string) {
  619. records, err := kd.Records(getSRVFQDN(kd, s, portName), false)
  620. require.NoError(t, err)
  621. assert.Equal(t, 1, len(records))
  622. assert.Equal(t, getServiceFQDN(kd, s), records[0].Host)
  623. }
  624. func assertNoSRVForNamedPort(t *testing.T, kd *KubeDNS, s *kapi.Service, portName string) {
  625. records, err := kd.Records(getSRVFQDN(kd, s, portName), false)
  626. require.Error(t, err)
  627. assert.Equal(t, 0, len(records))
  628. }
  629. func assertNoDNSForClusterIP(t *testing.T, kd *KubeDNS, s *kapi.Service) {
  630. serviceFQDN := getServiceFQDN(kd, s)
  631. queries := getEquivalentQueries(serviceFQDN, s.Namespace)
  632. for _, query := range queries {
  633. records, err := kd.Records(query, false)
  634. require.Error(t, err)
  635. assert.Equal(t, 0, len(records))
  636. }
  637. }
  638. func assertDNSForClusterIP(t *testing.T, kd *KubeDNS, s *kapi.Service) {
  639. serviceFQDN := getServiceFQDN(kd, s)
  640. queries := getEquivalentQueries(serviceFQDN, s.Namespace)
  641. for _, query := range queries {
  642. records, err := kd.Records(query, false)
  643. require.NoError(t, err)
  644. assert.Equal(t, 1, len(records))
  645. assert.Equal(t, s.Spec.ClusterIP, records[0].Host)
  646. }
  647. }
  648. func assertReverseRecord(t *testing.T, kd *KubeDNS, s *kapi.Service) {
  649. segments := reverseArray(strings.Split(s.Spec.ClusterIP, "."))
  650. reverseLookup := fmt.Sprintf("%s%s", strings.Join(segments, "."), arpaSuffix)
  651. reverseRecord, err := kd.ReverseRecord(reverseLookup)
  652. require.NoError(t, err)
  653. assert.Equal(t, kd.getServiceFQDN(s), reverseRecord.Host)
  654. }
  655. func assertNoReverseRecord(t *testing.T, kd *KubeDNS, s *kapi.Service) {
  656. segments := reverseArray(strings.Split(s.Spec.ClusterIP, "."))
  657. reverseLookup := fmt.Sprintf("%s%s", strings.Join(segments, "."), arpaSuffix)
  658. reverseRecord, err := kd.ReverseRecord(reverseLookup)
  659. require.Error(t, err)
  660. require.Nil(t, reverseRecord)
  661. }
  662. func getEquivalentQueries(serviceFQDN, namespace string) []string {
  663. return []string{
  664. serviceFQDN,
  665. strings.Replace(serviceFQDN, ".svc.", ".*.", 1),
  666. strings.Replace(serviceFQDN, namespace, "*", 1),
  667. strings.Replace(strings.Replace(serviceFQDN, namespace, "*", 1), ".svc.", ".*.", 1),
  668. "*." + serviceFQDN,
  669. }
  670. }
  671. func getFederationServiceFQDN(kd *KubeDNS, s *kapi.Service, federationName string) string {
  672. return fmt.Sprintf("%s.%s.%s.svc.%s", s.Name, s.Namespace, federationName, kd.domain)
  673. }
  674. func getServiceFQDN(kd *KubeDNS, s *kapi.Service) string {
  675. return fmt.Sprintf("%s.%s.svc.%s", s.Name, s.Namespace, kd.domain)
  676. }
  677. func getEndpointsFQDN(kd *KubeDNS, e *kapi.Endpoints) string {
  678. return fmt.Sprintf("%s.%s.svc.%s", e.Name, e.Namespace, kd.domain)
  679. }
  680. func getSRVFQDN(kd *KubeDNS, s *kapi.Service, portName string) string {
  681. return fmt.Sprintf("_%s._tcp.%s.%s.svc.%s", portName, s.Name, s.Namespace, kd.domain)
  682. }