utils_test.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  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 util
  14. import (
  15. "context"
  16. "net"
  17. "testing"
  18. "k8s.io/api/core/v1"
  19. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  20. "k8s.io/apimachinery/pkg/types"
  21. "k8s.io/apimachinery/pkg/util/sets"
  22. fake "k8s.io/kubernetes/pkg/proxy/util/testing"
  23. )
  24. func TestIsProxyableIP(t *testing.T) {
  25. testCases := []struct {
  26. ip string
  27. want error
  28. }{
  29. {"127.0.0.1", ErrAddressNotAllowed},
  30. {"127.0.0.2", ErrAddressNotAllowed},
  31. {"169.254.169.254", ErrAddressNotAllowed},
  32. {"169.254.1.1", ErrAddressNotAllowed},
  33. {"224.0.0.0", ErrAddressNotAllowed},
  34. {"10.0.0.1", nil},
  35. {"192.168.0.1", nil},
  36. {"172.16.0.1", nil},
  37. {"8.8.8.8", nil},
  38. {"::1", ErrAddressNotAllowed},
  39. {"fe80::", ErrAddressNotAllowed},
  40. {"ff02::", ErrAddressNotAllowed},
  41. {"ff01::", ErrAddressNotAllowed},
  42. {"2600::", nil},
  43. {"1", ErrAddressNotAllowed},
  44. {"", ErrAddressNotAllowed},
  45. }
  46. for i := range testCases {
  47. got := IsProxyableIP(testCases[i].ip)
  48. if testCases[i].want != got {
  49. t.Errorf("case %d: expected %v, got %v", i, testCases[i].want, got)
  50. }
  51. }
  52. }
  53. type dummyResolver struct {
  54. ips []string
  55. err error
  56. }
  57. func (r *dummyResolver) LookupIPAddr(ctx context.Context, host string) ([]net.IPAddr, error) {
  58. if r.err != nil {
  59. return nil, r.err
  60. }
  61. resp := []net.IPAddr{}
  62. for _, ipString := range r.ips {
  63. resp = append(resp, net.IPAddr{IP: net.ParseIP(ipString)})
  64. }
  65. return resp, nil
  66. }
  67. func TestIsProxyableHostname(t *testing.T) {
  68. testCases := []struct {
  69. hostname string
  70. ips []string
  71. want error
  72. }{
  73. {"k8s.io", []string{}, ErrNoAddresses},
  74. {"k8s.io", []string{"8.8.8.8"}, nil},
  75. {"k8s.io", []string{"169.254.169.254"}, ErrAddressNotAllowed},
  76. {"k8s.io", []string{"127.0.0.1", "8.8.8.8"}, ErrAddressNotAllowed},
  77. }
  78. for i := range testCases {
  79. resolv := dummyResolver{ips: testCases[i].ips}
  80. got := IsProxyableHostname(context.Background(), &resolv, testCases[i].hostname)
  81. if testCases[i].want != got {
  82. t.Errorf("case %d: expected %v, got %v", i, testCases[i].want, got)
  83. }
  84. }
  85. }
  86. func TestShouldSkipService(t *testing.T) {
  87. testCases := []struct {
  88. service *v1.Service
  89. svcName types.NamespacedName
  90. shouldSkip bool
  91. }{
  92. {
  93. // Cluster IP is None
  94. service: &v1.Service{
  95. ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"},
  96. Spec: v1.ServiceSpec{
  97. ClusterIP: v1.ClusterIPNone,
  98. },
  99. },
  100. svcName: types.NamespacedName{Namespace: "foo", Name: "bar"},
  101. shouldSkip: true,
  102. },
  103. {
  104. // Cluster IP is empty
  105. service: &v1.Service{
  106. ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"},
  107. Spec: v1.ServiceSpec{
  108. ClusterIP: "",
  109. },
  110. },
  111. svcName: types.NamespacedName{Namespace: "foo", Name: "bar"},
  112. shouldSkip: true,
  113. },
  114. {
  115. // ExternalName type service
  116. service: &v1.Service{
  117. ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"},
  118. Spec: v1.ServiceSpec{
  119. ClusterIP: "1.2.3.4",
  120. Type: v1.ServiceTypeExternalName,
  121. },
  122. },
  123. svcName: types.NamespacedName{Namespace: "foo", Name: "bar"},
  124. shouldSkip: true,
  125. },
  126. {
  127. // ClusterIP type service with ClusterIP set
  128. service: &v1.Service{
  129. ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"},
  130. Spec: v1.ServiceSpec{
  131. ClusterIP: "1.2.3.4",
  132. Type: v1.ServiceTypeClusterIP,
  133. },
  134. },
  135. svcName: types.NamespacedName{Namespace: "foo", Name: "bar"},
  136. shouldSkip: false,
  137. },
  138. {
  139. // NodePort type service with ClusterIP set
  140. service: &v1.Service{
  141. ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"},
  142. Spec: v1.ServiceSpec{
  143. ClusterIP: "1.2.3.4",
  144. Type: v1.ServiceTypeNodePort,
  145. },
  146. },
  147. svcName: types.NamespacedName{Namespace: "foo", Name: "bar"},
  148. shouldSkip: false,
  149. },
  150. {
  151. // LoadBalancer type service with ClusterIP set
  152. service: &v1.Service{
  153. ObjectMeta: metav1.ObjectMeta{Namespace: "foo", Name: "bar"},
  154. Spec: v1.ServiceSpec{
  155. ClusterIP: "1.2.3.4",
  156. Type: v1.ServiceTypeLoadBalancer,
  157. },
  158. },
  159. svcName: types.NamespacedName{Namespace: "foo", Name: "bar"},
  160. shouldSkip: false,
  161. },
  162. }
  163. for i := range testCases {
  164. skip := ShouldSkipService(testCases[i].svcName, testCases[i].service)
  165. if skip != testCases[i].shouldSkip {
  166. t.Errorf("case %d: expect %v, got %v", i, testCases[i].shouldSkip, skip)
  167. }
  168. }
  169. }
  170. type InterfaceAddrsPair struct {
  171. itf net.Interface
  172. addrs []net.Addr
  173. }
  174. func TestGetNodeAddressses(t *testing.T) {
  175. testCases := []struct {
  176. cidrs []string
  177. nw *fake.FakeNetwork
  178. itfAddrsPairs []InterfaceAddrsPair
  179. expected sets.String
  180. }{
  181. { // case 0
  182. cidrs: []string{"10.20.30.0/24"},
  183. nw: fake.NewFakeNetwork(),
  184. itfAddrsPairs: []InterfaceAddrsPair{
  185. {
  186. itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
  187. addrs: []net.Addr{fake.AddrStruct{Val: "10.20.30.51/24"}},
  188. },
  189. {
  190. itf: net.Interface{Index: 2, MTU: 0, Name: "eth1", HardwareAddr: nil, Flags: 0},
  191. addrs: []net.Addr{fake.AddrStruct{Val: "100.200.201.1/24"}},
  192. },
  193. },
  194. expected: sets.NewString("10.20.30.51"),
  195. },
  196. { // case 1
  197. cidrs: []string{"0.0.0.0/0"},
  198. nw: fake.NewFakeNetwork(),
  199. itfAddrsPairs: []InterfaceAddrsPair{
  200. {
  201. itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
  202. addrs: []net.Addr{fake.AddrStruct{Val: "10.20.30.51/24"}},
  203. },
  204. {
  205. itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
  206. addrs: []net.Addr{fake.AddrStruct{Val: "127.0.0.1/8"}},
  207. },
  208. },
  209. expected: sets.NewString("0.0.0.0/0"),
  210. },
  211. { // case 2
  212. cidrs: []string{"2001:db8::/32", "::1/128"},
  213. nw: fake.NewFakeNetwork(),
  214. itfAddrsPairs: []InterfaceAddrsPair{
  215. {
  216. itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
  217. addrs: []net.Addr{fake.AddrStruct{Val: "2001:db8::1/32"}},
  218. },
  219. {
  220. itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
  221. addrs: []net.Addr{fake.AddrStruct{Val: "::1/128"}},
  222. },
  223. },
  224. expected: sets.NewString("2001:db8::1", "::1"),
  225. },
  226. { // case 3
  227. cidrs: []string{"::/0"},
  228. nw: fake.NewFakeNetwork(),
  229. itfAddrsPairs: []InterfaceAddrsPair{
  230. {
  231. itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
  232. addrs: []net.Addr{fake.AddrStruct{Val: "2001:db8::1/32"}},
  233. },
  234. {
  235. itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
  236. addrs: []net.Addr{fake.AddrStruct{Val: "::1/128"}},
  237. },
  238. },
  239. expected: sets.NewString("::/0"),
  240. },
  241. { // case 4
  242. cidrs: []string{"127.0.0.1/32"},
  243. nw: fake.NewFakeNetwork(),
  244. itfAddrsPairs: []InterfaceAddrsPair{
  245. {
  246. itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
  247. addrs: []net.Addr{fake.AddrStruct{Val: "10.20.30.51/24"}},
  248. },
  249. {
  250. itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
  251. addrs: []net.Addr{fake.AddrStruct{Val: "127.0.0.1/8"}},
  252. },
  253. },
  254. expected: sets.NewString("127.0.0.1"),
  255. },
  256. { // case 5
  257. cidrs: []string{"127.0.0.0/8"},
  258. nw: fake.NewFakeNetwork(),
  259. itfAddrsPairs: []InterfaceAddrsPair{
  260. {
  261. itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
  262. addrs: []net.Addr{fake.AddrStruct{Val: "127.0.1.1/8"}},
  263. },
  264. },
  265. expected: sets.NewString("127.0.1.1"),
  266. },
  267. { // case 6
  268. cidrs: []string{"10.20.30.0/24", "100.200.201.0/24"},
  269. nw: fake.NewFakeNetwork(),
  270. itfAddrsPairs: []InterfaceAddrsPair{
  271. {
  272. itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
  273. addrs: []net.Addr{fake.AddrStruct{Val: "10.20.30.51/24"}},
  274. },
  275. {
  276. itf: net.Interface{Index: 2, MTU: 0, Name: "eth1", HardwareAddr: nil, Flags: 0},
  277. addrs: []net.Addr{fake.AddrStruct{Val: "100.200.201.1/24"}},
  278. },
  279. },
  280. expected: sets.NewString("10.20.30.51", "100.200.201.1"),
  281. },
  282. { // case 7
  283. cidrs: []string{"10.20.30.0/24", "100.200.201.0/24"},
  284. nw: fake.NewFakeNetwork(),
  285. itfAddrsPairs: []InterfaceAddrsPair{
  286. {
  287. itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
  288. addrs: []net.Addr{fake.AddrStruct{Val: "192.168.1.2/24"}},
  289. },
  290. {
  291. itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
  292. addrs: []net.Addr{fake.AddrStruct{Val: "127.0.0.1/8"}},
  293. },
  294. },
  295. expected: sets.NewString(),
  296. },
  297. { // case 8
  298. cidrs: []string{},
  299. nw: fake.NewFakeNetwork(),
  300. itfAddrsPairs: []InterfaceAddrsPair{
  301. {
  302. itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
  303. addrs: []net.Addr{fake.AddrStruct{Val: "192.168.1.2/24"}},
  304. },
  305. {
  306. itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
  307. addrs: []net.Addr{fake.AddrStruct{Val: "127.0.0.1/8"}},
  308. },
  309. },
  310. expected: sets.NewString("0.0.0.0/0", "::/0"),
  311. },
  312. { // case 9
  313. cidrs: []string{},
  314. nw: fake.NewFakeNetwork(),
  315. itfAddrsPairs: []InterfaceAddrsPair{
  316. {
  317. itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
  318. addrs: []net.Addr{fake.AddrStruct{Val: "2001:db8::1/32"}},
  319. },
  320. {
  321. itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
  322. addrs: []net.Addr{fake.AddrStruct{Val: "::1/128"}},
  323. },
  324. },
  325. expected: sets.NewString("0.0.0.0/0", "::/0"),
  326. },
  327. { // case 9
  328. cidrs: []string{"1.2.3.0/24", "0.0.0.0/0"},
  329. nw: fake.NewFakeNetwork(),
  330. itfAddrsPairs: []InterfaceAddrsPair{
  331. {
  332. itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
  333. addrs: []net.Addr{fake.AddrStruct{Val: "1.2.3.4/30"}},
  334. },
  335. },
  336. expected: sets.NewString("0.0.0.0/0"),
  337. },
  338. { // case 10
  339. cidrs: []string{"0.0.0.0/0", "1.2.3.0/24", "::1/128"},
  340. nw: fake.NewFakeNetwork(),
  341. itfAddrsPairs: []InterfaceAddrsPair{
  342. {
  343. itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
  344. addrs: []net.Addr{fake.AddrStruct{Val: "1.2.3.4/30"}},
  345. },
  346. {
  347. itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
  348. addrs: []net.Addr{fake.AddrStruct{Val: "::1/128"}},
  349. },
  350. },
  351. expected: sets.NewString("0.0.0.0/0", "::1"),
  352. },
  353. { // case 11
  354. cidrs: []string{"::/0", "1.2.3.0/24", "::1/128"},
  355. nw: fake.NewFakeNetwork(),
  356. itfAddrsPairs: []InterfaceAddrsPair{
  357. {
  358. itf: net.Interface{Index: 0, MTU: 0, Name: "eth0", HardwareAddr: nil, Flags: 0},
  359. addrs: []net.Addr{fake.AddrStruct{Val: "1.2.3.4/30"}},
  360. },
  361. {
  362. itf: net.Interface{Index: 1, MTU: 0, Name: "lo", HardwareAddr: nil, Flags: 0},
  363. addrs: []net.Addr{fake.AddrStruct{Val: "::1/128"}},
  364. },
  365. },
  366. expected: sets.NewString("::/0", "1.2.3.4"),
  367. },
  368. }
  369. for i := range testCases {
  370. for _, pair := range testCases[i].itfAddrsPairs {
  371. testCases[i].nw.AddInterfaceAddr(&pair.itf, pair.addrs)
  372. }
  373. addrList, err := GetNodeAddresses(testCases[i].cidrs, testCases[i].nw)
  374. if err != nil {
  375. t.Errorf("case [%d], unexpected error: %v", i, err)
  376. }
  377. if !addrList.Equal(testCases[i].expected) {
  378. t.Errorf("case [%d], unexpected mismatch, expected: %v, got: %v", i, testCases[i].expected, addrList)
  379. }
  380. }
  381. }
  382. func TestAppendPortIfNeeded(t *testing.T) {
  383. testCases := []struct {
  384. name string
  385. addr string
  386. port int32
  387. expect string
  388. }{
  389. {
  390. name: "IPv4 all-zeros bind address has port",
  391. addr: "0.0.0.0:12345",
  392. port: 23456,
  393. expect: "0.0.0.0:12345",
  394. },
  395. {
  396. name: "non-zeros IPv4 config",
  397. addr: "9.8.7.6",
  398. port: 12345,
  399. expect: "9.8.7.6:12345",
  400. },
  401. {
  402. name: "IPv6 \"[::]\" bind address has port",
  403. addr: "[::]:12345",
  404. port: 23456,
  405. expect: "[::]:12345",
  406. },
  407. {
  408. name: "IPv6 config",
  409. addr: "fd00:1::5",
  410. port: 23456,
  411. expect: "[fd00:1::5]:23456",
  412. },
  413. {
  414. name: "Invalid IPv6 Config",
  415. addr: "[fd00:1::5]",
  416. port: 12345,
  417. expect: "[fd00:1::5]",
  418. },
  419. }
  420. for i := range testCases {
  421. got := AppendPortIfNeeded(testCases[i].addr, testCases[i].port)
  422. if testCases[i].expect != got {
  423. t.Errorf("case %s: expected %v, got %v", testCases[i].name, testCases[i].expect, got)
  424. }
  425. }
  426. }