dns_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591
  1. /*
  2. Copyright 2017 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. "strings"
  16. "testing"
  17. apps "k8s.io/api/apps/v1"
  18. "k8s.io/api/core/v1"
  19. apierrors "k8s.io/apimachinery/pkg/api/errors"
  20. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  21. "k8s.io/apimachinery/pkg/runtime"
  22. clientsetfake "k8s.io/client-go/kubernetes/fake"
  23. clientsetscheme "k8s.io/client-go/kubernetes/scheme"
  24. core "k8s.io/client-go/testing"
  25. kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
  26. kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
  27. api "k8s.io/kubernetes/pkg/apis/core"
  28. )
  29. func TestCreateServiceAccount(t *testing.T) {
  30. tests := []struct {
  31. name string
  32. createErr error
  33. expectErr bool
  34. }{
  35. {
  36. "error-free case",
  37. nil,
  38. false,
  39. },
  40. {
  41. "duplication errors should be ignored",
  42. apierrors.NewAlreadyExists(api.Resource(""), ""),
  43. false,
  44. },
  45. {
  46. "unexpected errors should be returned",
  47. apierrors.NewUnauthorized(""),
  48. true,
  49. },
  50. }
  51. for _, tc := range tests {
  52. t.Run(tc.name, func(t *testing.T) {
  53. client := clientsetfake.NewSimpleClientset()
  54. if tc.createErr != nil {
  55. client.PrependReactor("create", "serviceaccounts", func(action core.Action) (bool, runtime.Object, error) {
  56. return true, nil, tc.createErr
  57. })
  58. }
  59. err := CreateServiceAccount(client)
  60. if tc.expectErr {
  61. if err == nil {
  62. t.Errorf("CreateServiceAccounts(%s) wanted err, got nil", tc.name)
  63. }
  64. return
  65. } else if !tc.expectErr && err != nil {
  66. t.Errorf("CreateServiceAccounts(%s) returned unexpected err: %v", tc.name, err)
  67. }
  68. wantResourcesCreated := 1
  69. if len(client.Actions()) != wantResourcesCreated {
  70. t.Errorf("CreateServiceAccounts(%s) should have made %d actions, but made %d", tc.name, wantResourcesCreated, len(client.Actions()))
  71. }
  72. for _, action := range client.Actions() {
  73. if action.GetVerb() != "create" || action.GetResource().Resource != "serviceaccounts" {
  74. t.Errorf("CreateServiceAccounts(%s) called [%v %v], but wanted [create serviceaccounts]",
  75. tc.name, action.GetVerb(), action.GetResource().Resource)
  76. }
  77. }
  78. })
  79. }
  80. }
  81. func TestCompileManifests(t *testing.T) {
  82. var tests = []struct {
  83. name string
  84. manifest string
  85. data interface{}
  86. }{
  87. {
  88. name: "KubeDNSDeployment manifest",
  89. manifest: KubeDNSDeployment,
  90. data: struct{ DeploymentName, KubeDNSImage, DNSMasqImage, SidecarImage, DNSBindAddr, DNSProbeAddr, DNSDomain, ControlPlaneTaintKey string }{
  91. DeploymentName: "foo",
  92. KubeDNSImage: "foo",
  93. DNSMasqImage: "foo",
  94. SidecarImage: "foo",
  95. DNSBindAddr: "foo",
  96. DNSProbeAddr: "foo",
  97. DNSDomain: "foo",
  98. ControlPlaneTaintKey: "foo",
  99. },
  100. },
  101. {
  102. name: "KubeDNSService manifest",
  103. manifest: KubeDNSService,
  104. data: struct{ DNSIP string }{
  105. DNSIP: "foo",
  106. },
  107. },
  108. {
  109. name: "CoreDNSDeployment manifest",
  110. manifest: CoreDNSDeployment,
  111. data: struct{ DeploymentName, Image, ControlPlaneTaintKey string }{
  112. DeploymentName: "foo",
  113. Image: "foo",
  114. ControlPlaneTaintKey: "foo",
  115. },
  116. },
  117. {
  118. name: "CoreDNSConfigMap manifest",
  119. manifest: CoreDNSConfigMap,
  120. data: struct{ DNSDomain, Federation, UpstreamNameserver, StubDomain string }{
  121. DNSDomain: "foo",
  122. Federation: "foo",
  123. UpstreamNameserver: "foo",
  124. StubDomain: "foo",
  125. },
  126. },
  127. }
  128. for _, rt := range tests {
  129. t.Run(rt.name, func(t *testing.T) {
  130. _, err := kubeadmutil.ParseTemplate(rt.manifest, rt.data)
  131. if err != nil {
  132. t.Errorf("unexpected ParseTemplate failure: %+v", err)
  133. }
  134. })
  135. }
  136. }
  137. func TestGetDNSIP(t *testing.T) {
  138. var tests = []struct {
  139. name, svcSubnet, expectedDNSIP string
  140. }{
  141. {
  142. name: "subnet mask 12",
  143. svcSubnet: "10.96.0.0/12",
  144. expectedDNSIP: "10.96.0.10",
  145. },
  146. {
  147. name: "subnet mask 26",
  148. svcSubnet: "10.87.116.64/26",
  149. expectedDNSIP: "10.87.116.74",
  150. },
  151. }
  152. for _, rt := range tests {
  153. t.Run(rt.name, func(t *testing.T) {
  154. dnsIP, err := kubeadmconstants.GetDNSIP(rt.svcSubnet)
  155. if err != nil {
  156. t.Fatalf("couldn't get dnsIP : %v", err)
  157. }
  158. actualDNSIP := dnsIP.String()
  159. if actualDNSIP != rt.expectedDNSIP {
  160. t.Errorf(
  161. "failed GetDNSIP\n\texpected: %s\n\t actual: %s",
  162. rt.expectedDNSIP,
  163. actualDNSIP,
  164. )
  165. }
  166. })
  167. }
  168. }
  169. func TestTranslateStubDomainKubeDNSToCoreDNS(t *testing.T) {
  170. testCases := []struct {
  171. name string
  172. configMap *v1.ConfigMap
  173. expectOne string
  174. expectTwo string
  175. }{
  176. {
  177. name: "valid call with multiple IPs",
  178. configMap: &v1.ConfigMap{
  179. ObjectMeta: metav1.ObjectMeta{
  180. Name: "kube-dns",
  181. Namespace: "kube-system",
  182. },
  183. Data: map[string]string{
  184. "stubDomains": `{"foo.com" : ["1.2.3.4:5300","3.3.3.3"], "my.cluster.local" : ["2.3.4.5"]}`,
  185. "upstreamNameservers": `["8.8.8.8", "8.8.4.4"]`,
  186. },
  187. },
  188. expectOne: `
  189. foo.com:53 {
  190. errors
  191. cache 30
  192. loop
  193. forward . 1.2.3.4:5300 3.3.3.3
  194. }
  195. my.cluster.local:53 {
  196. errors
  197. cache 30
  198. loop
  199. forward . 2.3.4.5
  200. }`,
  201. expectTwo: `
  202. my.cluster.local:53 {
  203. errors
  204. cache 30
  205. loop
  206. forward . 2.3.4.5
  207. }
  208. foo.com:53 {
  209. errors
  210. cache 30
  211. loop
  212. forward . 1.2.3.4:5300 3.3.3.3
  213. }`,
  214. },
  215. {
  216. name: "empty call",
  217. configMap: &v1.ConfigMap{
  218. ObjectMeta: metav1.ObjectMeta{
  219. Name: "kubedns",
  220. Namespace: "kube-system",
  221. },
  222. },
  223. expectOne: "",
  224. },
  225. {
  226. name: "valid call",
  227. configMap: &v1.ConfigMap{
  228. ObjectMeta: metav1.ObjectMeta{
  229. Name: "kube-dns",
  230. Namespace: "kube-system",
  231. },
  232. Data: map[string]string{
  233. "stubDomains": `{"foo.com" : ["1.2.3.4:5300"], "my.cluster.local" : ["2.3.4.5"]}`,
  234. "upstreamNameservers": `["8.8.8.8", "8.8.4.4"]`,
  235. },
  236. },
  237. expectOne: `
  238. foo.com:53 {
  239. errors
  240. cache 30
  241. loop
  242. forward . 1.2.3.4:5300
  243. }
  244. my.cluster.local:53 {
  245. errors
  246. cache 30
  247. loop
  248. forward . 2.3.4.5
  249. }`,
  250. expectTwo: `
  251. my.cluster.local:53 {
  252. errors
  253. cache 30
  254. loop
  255. forward . 2.3.4.5
  256. }
  257. foo.com:53 {
  258. errors
  259. cache 30
  260. loop
  261. forward . 1.2.3.4:5300
  262. }`,
  263. },
  264. {
  265. name: "If Hostname present: Omit Hostname",
  266. configMap: &v1.ConfigMap{
  267. ObjectMeta: metav1.ObjectMeta{
  268. Name: "kube-dns",
  269. Namespace: "kube-system",
  270. },
  271. Data: map[string]string{
  272. "stubDomains": `{"bar.com" : ["1.2.3.4:5300","service.consul"], "my.cluster.local" : ["2.3.4.5"], "foo.com" : ["service.consul"]}`,
  273. "upstreamNameservers": `["8.8.8.8", "8.8.4.4"]`,
  274. },
  275. },
  276. expectOne: `
  277. bar.com:53 {
  278. errors
  279. cache 30
  280. loop
  281. forward . 1.2.3.4:5300
  282. }
  283. my.cluster.local:53 {
  284. errors
  285. cache 30
  286. loop
  287. forward . 2.3.4.5
  288. }`,
  289. expectTwo: `
  290. my.cluster.local:53 {
  291. errors
  292. cache 30
  293. loop
  294. forward . 2.3.4.5
  295. }
  296. bar.com:53 {
  297. errors
  298. cache 30
  299. loop
  300. forward . 1.2.3.4:5300
  301. }`,
  302. },
  303. {
  304. name: "All hostname: return empty",
  305. configMap: &v1.ConfigMap{
  306. ObjectMeta: metav1.ObjectMeta{
  307. Name: "kube-dns",
  308. Namespace: "kube-system",
  309. },
  310. Data: map[string]string{
  311. "stubDomains": `{"foo.com" : ["service.consul"], "my.cluster.local" : ["ns.foo.com"]}`,
  312. "upstreamNameservers": `["8.8.8.8", "8.8.4.4"]`,
  313. },
  314. },
  315. expectOne: "",
  316. expectTwo: "",
  317. },
  318. {
  319. name: "missing stubDomains",
  320. configMap: &v1.ConfigMap{
  321. ObjectMeta: metav1.ObjectMeta{
  322. Name: "kube-dns",
  323. Namespace: "kube-system",
  324. },
  325. Data: map[string]string{
  326. "upstreamNameservers": `["8.8.8.8", "8.8.4.4"]`,
  327. },
  328. },
  329. expectOne: "",
  330. },
  331. }
  332. for _, testCase := range testCases {
  333. t.Run(testCase.name, func(t *testing.T) {
  334. out, err := translateStubDomainOfKubeDNSToForwardCoreDNS(kubeDNSStubDomain, testCase.configMap)
  335. if err != nil {
  336. t.Errorf("unexpected error: %v", err)
  337. }
  338. if !strings.EqualFold(out, testCase.expectOne) && !strings.EqualFold(out, testCase.expectTwo) {
  339. t.Errorf("expected to find %q or %q in output: %q", testCase.expectOne, testCase.expectTwo, out)
  340. }
  341. })
  342. }
  343. }
  344. func TestTranslateUpstreamKubeDNSToCoreDNS(t *testing.T) {
  345. testCases := []struct {
  346. name string
  347. configMap *v1.ConfigMap
  348. expect string
  349. }{
  350. {
  351. name: "expect resolv.conf",
  352. configMap: &v1.ConfigMap{
  353. ObjectMeta: metav1.ObjectMeta{
  354. Name: "kube-dns",
  355. Namespace: "kube-system",
  356. },
  357. },
  358. expect: "/etc/resolv.conf",
  359. },
  360. {
  361. name: "expect list of Name Server IP addresses",
  362. configMap: &v1.ConfigMap{
  363. ObjectMeta: metav1.ObjectMeta{
  364. Name: "kubedns",
  365. Namespace: "kube-system",
  366. },
  367. Data: map[string]string{
  368. "stubDomains": ` {"foo.com" : ["1.2.3.4:5300"], "my.cluster.local" : ["2.3.4.5"]}`,
  369. "upstreamNameservers": `["8.8.8.8", "8.8.4.4", "4.4.4.4"]`,
  370. },
  371. },
  372. expect: "8.8.8.8 8.8.4.4 4.4.4.4",
  373. },
  374. {
  375. name: "no stubDomains: expect list of Name Server IP addresses",
  376. configMap: &v1.ConfigMap{
  377. ObjectMeta: metav1.ObjectMeta{
  378. Name: "kubedns",
  379. Namespace: "kube-system",
  380. },
  381. Data: map[string]string{
  382. "upstreamNameservers": `["8.8.8.8", "8.8.4.4"]`,
  383. },
  384. },
  385. expect: "8.8.8.8 8.8.4.4",
  386. },
  387. {
  388. name: "Hostname present: expect NameServer to omit the hostname",
  389. configMap: &v1.ConfigMap{
  390. ObjectMeta: metav1.ObjectMeta{
  391. Name: "kubedns",
  392. Namespace: "kube-system",
  393. },
  394. Data: map[string]string{
  395. "upstreamNameservers": `["service.consul", "ns.foo.com", "8.8.4.4", "ns.moo.com", "ns.bar.com"]`,
  396. },
  397. },
  398. expect: "8.8.4.4",
  399. },
  400. {
  401. name: "All hostnames: return empty",
  402. configMap: &v1.ConfigMap{
  403. ObjectMeta: metav1.ObjectMeta{
  404. Name: "kube-dns",
  405. Namespace: "kube-system",
  406. },
  407. Data: map[string]string{
  408. "upstreamNameservers": `["service.consul", "ns.foo.com"]`,
  409. },
  410. },
  411. expect: "",
  412. },
  413. {
  414. name: "IPv6: expect list of Name Server IP addresses",
  415. configMap: &v1.ConfigMap{
  416. ObjectMeta: metav1.ObjectMeta{
  417. Name: "kubedns",
  418. Namespace: "kube-system",
  419. },
  420. Data: map[string]string{
  421. "upstreamNameservers": `["[2003::1]:53", "8.8.4.4"]`,
  422. },
  423. },
  424. expect: "[2003::1]:53 8.8.4.4",
  425. },
  426. }
  427. for _, testCase := range testCases {
  428. t.Run(testCase.name, func(t *testing.T) {
  429. out, err := translateUpstreamNameServerOfKubeDNSToUpstreamForwardCoreDNS(kubeDNSUpstreamNameservers, testCase.configMap)
  430. if err != nil {
  431. t.Errorf("unexpected error: %v", err)
  432. }
  433. if !strings.EqualFold(out, testCase.expect) {
  434. t.Errorf("expected to find %q in output: %q", testCase.expect, out)
  435. }
  436. })
  437. }
  438. }
  439. func TestTranslateFederationKubeDNSToCoreDNS(t *testing.T) {
  440. testCases := []struct {
  441. name string
  442. configMap *v1.ConfigMap
  443. expectOne string
  444. expectTwo string
  445. }{
  446. {
  447. name: "valid call",
  448. configMap: &v1.ConfigMap{
  449. ObjectMeta: metav1.ObjectMeta{
  450. Name: "kube-dns",
  451. Namespace: "kube-system",
  452. },
  453. Data: map[string]string{
  454. "federations": `{"foo" : "foo.feddomain.com", "bar" : "bar.feddomain.com"}`,
  455. "stubDomains": `{"foo.com" : ["1.2.3.4:5300","3.3.3.3"], "my.cluster.local" : ["2.3.4.5"]}`,
  456. "upstreamNameservers": `["8.8.8.8", "8.8.4.4"]`,
  457. },
  458. },
  459. expectOne: `
  460. federation cluster.local {
  461. foo foo.feddomain.com
  462. bar bar.feddomain.com
  463. }`,
  464. expectTwo: `
  465. federation cluster.local {
  466. bar bar.feddomain.com
  467. foo foo.feddomain.com
  468. }`,
  469. },
  470. {
  471. name: "empty data",
  472. configMap: &v1.ConfigMap{
  473. ObjectMeta: metav1.ObjectMeta{
  474. Name: "kubedns",
  475. Namespace: "kube-system",
  476. },
  477. },
  478. expectOne: "",
  479. expectTwo: "",
  480. },
  481. {
  482. name: "missing federations data",
  483. configMap: &v1.ConfigMap{
  484. ObjectMeta: metav1.ObjectMeta{
  485. Name: "kube-dns",
  486. Namespace: "kube-system",
  487. },
  488. Data: map[string]string{
  489. "stubDomains": `{"foo.com" : ["1.2.3.4:5300"], "my.cluster.local" : ["2.3.4.5"]}`,
  490. "upstreamNameservers": `["8.8.8.8", "8.8.4.4"]`,
  491. },
  492. },
  493. expectOne: "",
  494. expectTwo: "",
  495. },
  496. }
  497. for _, testCase := range testCases {
  498. t.Run(testCase.name, func(t *testing.T) {
  499. out, err := translateFederationsofKubeDNSToCoreDNS(kubeDNSFederation, "cluster.local", testCase.configMap)
  500. if err != nil {
  501. t.Errorf("unexpected error: %v", err)
  502. }
  503. if !strings.EqualFold(out, testCase.expectOne) && !strings.EqualFold(out, testCase.expectTwo) {
  504. t.Errorf("expected to find %q or %q in output: %q", testCase.expectOne, testCase.expectTwo, out)
  505. }
  506. })
  507. }
  508. }
  509. func TestDeploymentsHaveSystemClusterCriticalPriorityClassName(t *testing.T) {
  510. testCases := []struct {
  511. name string
  512. manifest string
  513. data interface{}
  514. }{
  515. {
  516. name: "KubeDNSDeployment",
  517. manifest: KubeDNSDeployment,
  518. data: struct{ DeploymentName, KubeDNSImage, DNSMasqImage, SidecarImage, DNSBindAddr, DNSProbeAddr, DNSDomain, ControlPlaneTaintKey string }{
  519. DeploymentName: "foo",
  520. KubeDNSImage: "foo",
  521. DNSMasqImage: "foo",
  522. SidecarImage: "foo",
  523. DNSBindAddr: "foo",
  524. DNSProbeAddr: "foo",
  525. DNSDomain: "foo",
  526. ControlPlaneTaintKey: "foo",
  527. },
  528. },
  529. {
  530. name: "CoreDNSDeployment",
  531. manifest: CoreDNSDeployment,
  532. data: struct{ DeploymentName, Image, ControlPlaneTaintKey string }{
  533. DeploymentName: "foo",
  534. Image: "foo",
  535. ControlPlaneTaintKey: "foo",
  536. },
  537. },
  538. }
  539. for _, testCase := range testCases {
  540. t.Run(testCase.name, func(t *testing.T) {
  541. deploymentBytes, _ := kubeadmutil.ParseTemplate(testCase.manifest, testCase.data)
  542. deployment := &apps.Deployment{}
  543. if err := runtime.DecodeInto(clientsetscheme.Codecs.UniversalDecoder(), deploymentBytes, deployment); err != nil {
  544. t.Errorf("unexpected error: %v", err)
  545. }
  546. if deployment.Spec.Template.Spec.PriorityClassName != "system-cluster-critical" {
  547. t.Errorf("expected to see system-cluster-critical priority class name. Got %q instead", deployment.Spec.Template.Spec.PriorityClassName)
  548. }
  549. })
  550. }
  551. }