service_test.go 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  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 proxy
  14. import (
  15. "net"
  16. "reflect"
  17. "testing"
  18. "github.com/davecgh/go-spew/spew"
  19. "k8s.io/api/core/v1"
  20. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  21. "k8s.io/apimachinery/pkg/types"
  22. "k8s.io/apimachinery/pkg/util/intstr"
  23. "k8s.io/apimachinery/pkg/util/sets"
  24. )
  25. const testHostname = "test-hostname"
  26. func makeTestServiceInfo(clusterIP string, port int, protocol string, healthcheckNodePort int, svcInfoFuncs ...func(*BaseServiceInfo)) *BaseServiceInfo {
  27. info := &BaseServiceInfo{
  28. clusterIP: net.ParseIP(clusterIP),
  29. port: port,
  30. protocol: v1.Protocol(protocol),
  31. }
  32. if healthcheckNodePort != 0 {
  33. info.healthCheckNodePort = healthcheckNodePort
  34. }
  35. for _, svcInfoFunc := range svcInfoFuncs {
  36. svcInfoFunc(info)
  37. }
  38. return info
  39. }
  40. func makeTestService(namespace, name string, svcFunc func(*v1.Service)) *v1.Service {
  41. svc := &v1.Service{
  42. ObjectMeta: metav1.ObjectMeta{
  43. Name: name,
  44. Namespace: namespace,
  45. Annotations: map[string]string{},
  46. },
  47. Spec: v1.ServiceSpec{},
  48. Status: v1.ServiceStatus{},
  49. }
  50. svcFunc(svc)
  51. return svc
  52. }
  53. func addTestPort(array []v1.ServicePort, name string, protocol v1.Protocol, port, nodeport int32, targetPort int) []v1.ServicePort {
  54. svcPort := v1.ServicePort{
  55. Name: name,
  56. Protocol: protocol,
  57. Port: port,
  58. NodePort: nodeport,
  59. TargetPort: intstr.FromInt(targetPort),
  60. }
  61. return append(array, svcPort)
  62. }
  63. func makeNSN(namespace, name string) types.NamespacedName {
  64. return types.NamespacedName{Namespace: namespace, Name: name}
  65. }
  66. func makeServicePortName(ns, name, port string, protocol v1.Protocol) ServicePortName {
  67. return ServicePortName{
  68. NamespacedName: makeNSN(ns, name),
  69. Port: port,
  70. Protocol: protocol,
  71. }
  72. }
  73. func TestServiceToServiceMap(t *testing.T) {
  74. svcTracker := NewServiceChangeTracker(nil, nil, nil)
  75. trueVal := true
  76. falseVal := false
  77. testClusterIPv4 := "10.0.0.1"
  78. testExternalIPv4 := "8.8.8.8"
  79. testSourceRangeIPv4 := "0.0.0.0/1"
  80. testClusterIPv6 := "2001:db8:85a3:0:0:8a2e:370:7334"
  81. testExternalIPv6 := "2001:db8:85a3:0:0:8a2e:370:7335"
  82. testSourceRangeIPv6 := "2001:db8::/32"
  83. testCases := []struct {
  84. desc string
  85. service *v1.Service
  86. expected map[ServicePortName]*BaseServiceInfo
  87. isIPv6Mode *bool
  88. }{
  89. {
  90. desc: "nothing",
  91. service: nil,
  92. expected: map[ServicePortName]*BaseServiceInfo{},
  93. },
  94. {
  95. desc: "headless service",
  96. service: makeTestService("ns2", "headless", func(svc *v1.Service) {
  97. svc.Spec.Type = v1.ServiceTypeClusterIP
  98. svc.Spec.ClusterIP = v1.ClusterIPNone
  99. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "rpc", "UDP", 1234, 0, 0)
  100. }),
  101. expected: map[ServicePortName]*BaseServiceInfo{},
  102. },
  103. {
  104. desc: "headless sctp service",
  105. service: makeTestService("ns2", "headless", func(svc *v1.Service) {
  106. svc.Spec.Type = v1.ServiceTypeClusterIP
  107. svc.Spec.ClusterIP = v1.ClusterIPNone
  108. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "sip", "SCTP", 7777, 0, 0)
  109. }),
  110. expected: map[ServicePortName]*BaseServiceInfo{},
  111. },
  112. {
  113. desc: "headless service without port",
  114. service: makeTestService("ns2", "headless-without-port", func(svc *v1.Service) {
  115. svc.Spec.Type = v1.ServiceTypeClusterIP
  116. svc.Spec.ClusterIP = v1.ClusterIPNone
  117. }),
  118. expected: map[ServicePortName]*BaseServiceInfo{},
  119. },
  120. {
  121. desc: "cluster ip service",
  122. service: makeTestService("ns2", "cluster-ip", func(svc *v1.Service) {
  123. svc.Spec.Type = v1.ServiceTypeClusterIP
  124. svc.Spec.ClusterIP = "172.16.55.4"
  125. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "p1", "UDP", 1234, 4321, 0)
  126. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "p2", "UDP", 1235, 5321, 0)
  127. }),
  128. expected: map[ServicePortName]*BaseServiceInfo{
  129. makeServicePortName("ns2", "cluster-ip", "p1", v1.ProtocolUDP): makeTestServiceInfo("172.16.55.4", 1234, "UDP", 0),
  130. makeServicePortName("ns2", "cluster-ip", "p2", v1.ProtocolUDP): makeTestServiceInfo("172.16.55.4", 1235, "UDP", 0),
  131. },
  132. },
  133. {
  134. desc: "nodeport service",
  135. service: makeTestService("ns2", "node-port", func(svc *v1.Service) {
  136. svc.Spec.Type = v1.ServiceTypeNodePort
  137. svc.Spec.ClusterIP = "172.16.55.10"
  138. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "port1", "UDP", 345, 678, 0)
  139. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "port2", "TCP", 344, 677, 0)
  140. }),
  141. expected: map[ServicePortName]*BaseServiceInfo{
  142. makeServicePortName("ns2", "node-port", "port1", v1.ProtocolUDP): makeTestServiceInfo("172.16.55.10", 345, "UDP", 0),
  143. makeServicePortName("ns2", "node-port", "port2", v1.ProtocolTCP): makeTestServiceInfo("172.16.55.10", 344, "TCP", 0),
  144. },
  145. },
  146. {
  147. desc: "load balancer service",
  148. service: makeTestService("ns1", "load-balancer", func(svc *v1.Service) {
  149. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  150. svc.Spec.ClusterIP = "172.16.55.11"
  151. svc.Spec.LoadBalancerIP = "5.6.7.8"
  152. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "port3", "UDP", 8675, 30061, 7000)
  153. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "port4", "UDP", 8676, 30062, 7001)
  154. svc.Status.LoadBalancer.Ingress = []v1.LoadBalancerIngress{{IP: "10.1.2.4"}}
  155. }),
  156. expected: map[ServicePortName]*BaseServiceInfo{
  157. makeServicePortName("ns1", "load-balancer", "port3", v1.ProtocolUDP): makeTestServiceInfo("172.16.55.11", 8675, "UDP", 0, func(info *BaseServiceInfo) {
  158. info.loadBalancerStatus.Ingress = []v1.LoadBalancerIngress{{IP: "10.1.2.4"}}
  159. }),
  160. makeServicePortName("ns1", "load-balancer", "port4", v1.ProtocolUDP): makeTestServiceInfo("172.16.55.11", 8676, "UDP", 0, func(info *BaseServiceInfo) {
  161. info.loadBalancerStatus.Ingress = []v1.LoadBalancerIngress{{IP: "10.1.2.4"}}
  162. }),
  163. },
  164. },
  165. {
  166. desc: "load balancer service with only local traffic policy",
  167. service: makeTestService("ns1", "only-local-load-balancer", func(svc *v1.Service) {
  168. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  169. svc.Spec.ClusterIP = "172.16.55.12"
  170. svc.Spec.LoadBalancerIP = "5.6.7.8"
  171. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "portx", "UDP", 8677, 30063, 7002)
  172. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "porty", "UDP", 8678, 30064, 7003)
  173. svc.Status.LoadBalancer.Ingress = []v1.LoadBalancerIngress{{IP: "10.1.2.3"}}
  174. svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
  175. svc.Spec.HealthCheckNodePort = 345
  176. }),
  177. expected: map[ServicePortName]*BaseServiceInfo{
  178. makeServicePortName("ns1", "only-local-load-balancer", "portx", v1.ProtocolUDP): makeTestServiceInfo("172.16.55.12", 8677, "UDP", 345, func(info *BaseServiceInfo) {
  179. info.loadBalancerStatus.Ingress = []v1.LoadBalancerIngress{{IP: "10.1.2.3"}}
  180. }),
  181. makeServicePortName("ns1", "only-local-load-balancer", "porty", v1.ProtocolUDP): makeTestServiceInfo("172.16.55.12", 8678, "UDP", 345, func(info *BaseServiceInfo) {
  182. info.loadBalancerStatus.Ingress = []v1.LoadBalancerIngress{{IP: "10.1.2.3"}}
  183. }),
  184. },
  185. },
  186. {
  187. desc: "external name service",
  188. service: makeTestService("ns2", "external-name", func(svc *v1.Service) {
  189. svc.Spec.Type = v1.ServiceTypeExternalName
  190. svc.Spec.ClusterIP = "172.16.55.4" // Should be ignored
  191. svc.Spec.ExternalName = "foo2.bar.com"
  192. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "portz", "UDP", 1235, 5321, 0)
  193. }),
  194. expected: map[ServicePortName]*BaseServiceInfo{},
  195. },
  196. {
  197. desc: "service with ipv6 clusterIP under ipv4 mode, service should be filtered",
  198. service: &v1.Service{
  199. ObjectMeta: metav1.ObjectMeta{
  200. Name: "invalidIPv6InIPV4Mode",
  201. Namespace: "test",
  202. },
  203. Spec: v1.ServiceSpec{
  204. ClusterIP: testClusterIPv6,
  205. Ports: []v1.ServicePort{
  206. {
  207. Name: "testPort",
  208. Port: int32(12345),
  209. Protocol: v1.ProtocolTCP,
  210. },
  211. },
  212. },
  213. Status: v1.ServiceStatus{
  214. LoadBalancer: v1.LoadBalancerStatus{
  215. Ingress: []v1.LoadBalancerIngress{
  216. {IP: testExternalIPv4},
  217. {IP: testExternalIPv6},
  218. },
  219. },
  220. },
  221. },
  222. isIPv6Mode: &falseVal,
  223. },
  224. {
  225. desc: "service with ipv4 clusterIP under ipv6 mode, service should be filtered",
  226. service: &v1.Service{
  227. ObjectMeta: metav1.ObjectMeta{
  228. Name: "invalidIPv4InIPV6Mode",
  229. Namespace: "test",
  230. },
  231. Spec: v1.ServiceSpec{
  232. ClusterIP: testClusterIPv4,
  233. Ports: []v1.ServicePort{
  234. {
  235. Name: "testPort",
  236. Port: int32(12345),
  237. Protocol: v1.ProtocolTCP,
  238. },
  239. },
  240. },
  241. Status: v1.ServiceStatus{
  242. LoadBalancer: v1.LoadBalancerStatus{
  243. Ingress: []v1.LoadBalancerIngress{
  244. {IP: testExternalIPv4},
  245. {IP: testExternalIPv6},
  246. },
  247. },
  248. },
  249. },
  250. isIPv6Mode: &trueVal,
  251. },
  252. {
  253. desc: "service with ipv4 configurations under ipv4 mode",
  254. service: &v1.Service{
  255. ObjectMeta: metav1.ObjectMeta{
  256. Name: "validIPv4",
  257. Namespace: "test",
  258. },
  259. Spec: v1.ServiceSpec{
  260. ClusterIP: testClusterIPv4,
  261. ExternalIPs: []string{testExternalIPv4},
  262. LoadBalancerSourceRanges: []string{testSourceRangeIPv4},
  263. Ports: []v1.ServicePort{
  264. {
  265. Name: "testPort",
  266. Port: int32(12345),
  267. Protocol: v1.ProtocolTCP,
  268. },
  269. },
  270. },
  271. Status: v1.ServiceStatus{
  272. LoadBalancer: v1.LoadBalancerStatus{
  273. Ingress: []v1.LoadBalancerIngress{
  274. {IP: testExternalIPv4},
  275. {IP: testExternalIPv6},
  276. },
  277. },
  278. },
  279. },
  280. expected: map[ServicePortName]*BaseServiceInfo{
  281. makeServicePortName("test", "validIPv4", "testPort", v1.ProtocolTCP): makeTestServiceInfo(testClusterIPv4, 12345, "TCP", 0, func(info *BaseServiceInfo) {
  282. info.externalIPs = []string{testExternalIPv4}
  283. info.loadBalancerSourceRanges = []string{testSourceRangeIPv4}
  284. info.loadBalancerStatus.Ingress = []v1.LoadBalancerIngress{{IP: testExternalIPv4}}
  285. }),
  286. },
  287. isIPv6Mode: &falseVal,
  288. },
  289. {
  290. desc: "service with ipv6 configurations under ipv6 mode",
  291. service: &v1.Service{
  292. ObjectMeta: metav1.ObjectMeta{
  293. Name: "validIPv6",
  294. Namespace: "test",
  295. },
  296. Spec: v1.ServiceSpec{
  297. ClusterIP: testClusterIPv6,
  298. ExternalIPs: []string{testExternalIPv6},
  299. LoadBalancerSourceRanges: []string{testSourceRangeIPv6},
  300. Ports: []v1.ServicePort{
  301. {
  302. Name: "testPort",
  303. Port: int32(12345),
  304. Protocol: v1.ProtocolTCP,
  305. },
  306. },
  307. },
  308. Status: v1.ServiceStatus{
  309. LoadBalancer: v1.LoadBalancerStatus{
  310. Ingress: []v1.LoadBalancerIngress{
  311. {IP: testExternalIPv4},
  312. {IP: testExternalIPv6},
  313. },
  314. },
  315. },
  316. },
  317. expected: map[ServicePortName]*BaseServiceInfo{
  318. makeServicePortName("test", "validIPv6", "testPort", v1.ProtocolTCP): makeTestServiceInfo(testClusterIPv6, 12345, "TCP", 0, func(info *BaseServiceInfo) {
  319. info.externalIPs = []string{testExternalIPv6}
  320. info.loadBalancerSourceRanges = []string{testSourceRangeIPv6}
  321. info.loadBalancerStatus.Ingress = []v1.LoadBalancerIngress{{IP: testExternalIPv6}}
  322. }),
  323. },
  324. isIPv6Mode: &trueVal,
  325. },
  326. {
  327. desc: "service with both ipv4 and ipv6 configurations under ipv4 mode, ipv6 fields should be filtered",
  328. service: &v1.Service{
  329. ObjectMeta: metav1.ObjectMeta{
  330. Name: "filterIPv6InIPV4Mode",
  331. Namespace: "test",
  332. },
  333. Spec: v1.ServiceSpec{
  334. ClusterIP: testClusterIPv4,
  335. ExternalIPs: []string{testExternalIPv4, testExternalIPv6},
  336. LoadBalancerSourceRanges: []string{testSourceRangeIPv4, testSourceRangeIPv6},
  337. Ports: []v1.ServicePort{
  338. {
  339. Name: "testPort",
  340. Port: int32(12345),
  341. Protocol: v1.ProtocolTCP,
  342. },
  343. },
  344. },
  345. Status: v1.ServiceStatus{
  346. LoadBalancer: v1.LoadBalancerStatus{
  347. Ingress: []v1.LoadBalancerIngress{
  348. {IP: testExternalIPv4},
  349. {IP: testExternalIPv6},
  350. },
  351. },
  352. },
  353. },
  354. expected: map[ServicePortName]*BaseServiceInfo{
  355. makeServicePortName("test", "filterIPv6InIPV4Mode", "testPort", v1.ProtocolTCP): makeTestServiceInfo(testClusterIPv4, 12345, "TCP", 0, func(info *BaseServiceInfo) {
  356. info.externalIPs = []string{testExternalIPv4}
  357. info.loadBalancerSourceRanges = []string{testSourceRangeIPv4}
  358. info.loadBalancerStatus.Ingress = []v1.LoadBalancerIngress{{IP: testExternalIPv4}}
  359. }),
  360. },
  361. isIPv6Mode: &falseVal,
  362. },
  363. {
  364. desc: "service with both ipv4 and ipv6 configurations under ipv6 mode, ipv4 fields should be filtered",
  365. service: &v1.Service{
  366. ObjectMeta: metav1.ObjectMeta{
  367. Name: "filterIPv4InIPV6Mode",
  368. Namespace: "test",
  369. },
  370. Spec: v1.ServiceSpec{
  371. ClusterIP: testClusterIPv6,
  372. ExternalIPs: []string{testExternalIPv4, testExternalIPv6},
  373. LoadBalancerSourceRanges: []string{testSourceRangeIPv4, testSourceRangeIPv6},
  374. Ports: []v1.ServicePort{
  375. {
  376. Name: "testPort",
  377. Port: int32(12345),
  378. Protocol: v1.ProtocolTCP,
  379. },
  380. },
  381. },
  382. Status: v1.ServiceStatus{
  383. LoadBalancer: v1.LoadBalancerStatus{
  384. Ingress: []v1.LoadBalancerIngress{
  385. {IP: testExternalIPv4},
  386. {IP: testExternalIPv6},
  387. },
  388. },
  389. },
  390. },
  391. expected: map[ServicePortName]*BaseServiceInfo{
  392. makeServicePortName("test", "filterIPv4InIPV6Mode", "testPort", v1.ProtocolTCP): makeTestServiceInfo(testClusterIPv6, 12345, "TCP", 0, func(info *BaseServiceInfo) {
  393. info.externalIPs = []string{testExternalIPv6}
  394. info.loadBalancerSourceRanges = []string{testSourceRangeIPv6}
  395. info.loadBalancerStatus.Ingress = []v1.LoadBalancerIngress{{IP: testExternalIPv6}}
  396. }),
  397. },
  398. isIPv6Mode: &trueVal,
  399. },
  400. }
  401. for _, tc := range testCases {
  402. svcTracker.isIPv6Mode = tc.isIPv6Mode
  403. // outputs
  404. newServices := svcTracker.serviceToServiceMap(tc.service)
  405. if len(newServices) != len(tc.expected) {
  406. t.Errorf("[%s] expected %d new, got %d: %v", tc.desc, len(tc.expected), len(newServices), spew.Sdump(newServices))
  407. }
  408. for svcKey, expectedInfo := range tc.expected {
  409. svcInfo, _ := newServices[svcKey].(*BaseServiceInfo)
  410. if !svcInfo.clusterIP.Equal(expectedInfo.clusterIP) ||
  411. svcInfo.port != expectedInfo.port ||
  412. svcInfo.protocol != expectedInfo.protocol ||
  413. svcInfo.healthCheckNodePort != expectedInfo.healthCheckNodePort ||
  414. !sets.NewString(svcInfo.externalIPs...).Equal(sets.NewString(expectedInfo.externalIPs...)) ||
  415. !sets.NewString(svcInfo.loadBalancerSourceRanges...).Equal(sets.NewString(expectedInfo.loadBalancerSourceRanges...)) ||
  416. !reflect.DeepEqual(svcInfo.loadBalancerStatus, expectedInfo.loadBalancerStatus) {
  417. t.Errorf("[%s] expected new[%v]to be %v, got %v", tc.desc, svcKey, expectedInfo, *svcInfo)
  418. }
  419. }
  420. }
  421. }
  422. type FakeProxier struct {
  423. endpointsChanges *EndpointChangeTracker
  424. serviceChanges *ServiceChangeTracker
  425. serviceMap ServiceMap
  426. endpointsMap EndpointsMap
  427. hostname string
  428. }
  429. func newFakeProxier() *FakeProxier {
  430. return &FakeProxier{
  431. serviceMap: make(ServiceMap),
  432. serviceChanges: NewServiceChangeTracker(nil, nil, nil),
  433. endpointsMap: make(EndpointsMap),
  434. endpointsChanges: NewEndpointChangeTracker(testHostname, nil, nil, nil, false),
  435. }
  436. }
  437. func makeServiceMap(fake *FakeProxier, allServices ...*v1.Service) {
  438. for i := range allServices {
  439. fake.addService(allServices[i])
  440. }
  441. }
  442. func (fake *FakeProxier) addService(service *v1.Service) {
  443. fake.serviceChanges.Update(nil, service)
  444. }
  445. func (fake *FakeProxier) updateService(oldService *v1.Service, service *v1.Service) {
  446. fake.serviceChanges.Update(oldService, service)
  447. }
  448. func (fake *FakeProxier) deleteService(service *v1.Service) {
  449. fake.serviceChanges.Update(service, nil)
  450. }
  451. func TestUpdateServiceMapHeadless(t *testing.T) {
  452. fp := newFakeProxier()
  453. makeServiceMap(fp,
  454. makeTestService("ns2", "headless", func(svc *v1.Service) {
  455. svc.Spec.Type = v1.ServiceTypeClusterIP
  456. svc.Spec.ClusterIP = v1.ClusterIPNone
  457. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "rpc", "UDP", 1234, 0, 0)
  458. }),
  459. makeTestService("ns2", "headless-without-port", func(svc *v1.Service) {
  460. svc.Spec.Type = v1.ServiceTypeClusterIP
  461. svc.Spec.ClusterIP = v1.ClusterIPNone
  462. }),
  463. )
  464. // Headless service should be ignored
  465. result := UpdateServiceMap(fp.serviceMap, fp.serviceChanges)
  466. if len(fp.serviceMap) != 0 {
  467. t.Errorf("expected service map length 0, got %d", len(fp.serviceMap))
  468. }
  469. // No proxied services, so no healthchecks
  470. if len(result.HCServiceNodePorts) != 0 {
  471. t.Errorf("expected healthcheck ports length 0, got %d", len(result.HCServiceNodePorts))
  472. }
  473. if len(result.UDPStaleClusterIP) != 0 {
  474. t.Errorf("expected stale UDP services length 0, got %d", len(result.UDPStaleClusterIP))
  475. }
  476. }
  477. func TestUpdateServiceTypeExternalName(t *testing.T) {
  478. fp := newFakeProxier()
  479. makeServiceMap(fp,
  480. makeTestService("ns2", "external-name", func(svc *v1.Service) {
  481. svc.Spec.Type = v1.ServiceTypeExternalName
  482. svc.Spec.ClusterIP = "172.16.55.4" // Should be ignored
  483. svc.Spec.ExternalName = "foo2.bar.com"
  484. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "blah", "UDP", 1235, 5321, 0)
  485. }),
  486. )
  487. result := UpdateServiceMap(fp.serviceMap, fp.serviceChanges)
  488. if len(fp.serviceMap) != 0 {
  489. t.Errorf("expected service map length 0, got %v", fp.serviceMap)
  490. }
  491. // No proxied services, so no healthchecks
  492. if len(result.HCServiceNodePorts) != 0 {
  493. t.Errorf("expected healthcheck ports length 0, got %v", result.HCServiceNodePorts)
  494. }
  495. if len(result.UDPStaleClusterIP) != 0 {
  496. t.Errorf("expected stale UDP services length 0, got %v", result.UDPStaleClusterIP)
  497. }
  498. }
  499. func TestBuildServiceMapAddRemove(t *testing.T) {
  500. fp := newFakeProxier()
  501. services := []*v1.Service{
  502. makeTestService("ns2", "cluster-ip", func(svc *v1.Service) {
  503. svc.Spec.Type = v1.ServiceTypeClusterIP
  504. svc.Spec.ClusterIP = "172.16.55.4"
  505. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "port1", "UDP", 1234, 4321, 0)
  506. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "port2", "UDP", 1235, 5321, 0)
  507. }),
  508. makeTestService("ns2", "node-port", func(svc *v1.Service) {
  509. svc.Spec.Type = v1.ServiceTypeNodePort
  510. svc.Spec.ClusterIP = "172.16.55.10"
  511. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "port1", "UDP", 345, 678, 0)
  512. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "port2", "TCP", 344, 677, 0)
  513. }),
  514. makeTestService("ns1", "load-balancer", func(svc *v1.Service) {
  515. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  516. svc.Spec.ClusterIP = "172.16.55.11"
  517. svc.Spec.LoadBalancerIP = "5.6.7.8"
  518. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "foobar", "UDP", 8675, 30061, 7000)
  519. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "baz", "UDP", 8676, 30062, 7001)
  520. svc.Status.LoadBalancer = v1.LoadBalancerStatus{
  521. Ingress: []v1.LoadBalancerIngress{
  522. {IP: "10.1.2.4"},
  523. },
  524. }
  525. }),
  526. makeTestService("ns1", "only-local-load-balancer", func(svc *v1.Service) {
  527. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  528. svc.Spec.ClusterIP = "172.16.55.12"
  529. svc.Spec.LoadBalancerIP = "5.6.7.8"
  530. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "foobar2", "UDP", 8677, 30063, 7002)
  531. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "baz", "UDP", 8678, 30064, 7003)
  532. svc.Status.LoadBalancer = v1.LoadBalancerStatus{
  533. Ingress: []v1.LoadBalancerIngress{
  534. {IP: "10.1.2.3"},
  535. },
  536. }
  537. svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
  538. svc.Spec.HealthCheckNodePort = 345
  539. }),
  540. }
  541. for i := range services {
  542. fp.addService(services[i])
  543. }
  544. result := UpdateServiceMap(fp.serviceMap, fp.serviceChanges)
  545. if len(fp.serviceMap) != 8 {
  546. t.Errorf("expected service map length 2, got %v", fp.serviceMap)
  547. }
  548. // The only-local-loadbalancer ones get added
  549. if len(result.HCServiceNodePorts) != 1 {
  550. t.Errorf("expected 1 healthcheck port, got %v", result.HCServiceNodePorts)
  551. } else {
  552. nsn := makeNSN("ns1", "only-local-load-balancer")
  553. if port, found := result.HCServiceNodePorts[nsn]; !found || port != 345 {
  554. t.Errorf("expected healthcheck port [%q]=345: got %v", nsn, result.HCServiceNodePorts)
  555. }
  556. }
  557. if len(result.UDPStaleClusterIP) != 0 {
  558. // Services only added, so nothing stale yet
  559. t.Errorf("expected stale UDP services length 0, got %d", len(result.UDPStaleClusterIP))
  560. }
  561. // Remove some stuff
  562. // oneService is a modification of services[0] with removed first port.
  563. oneService := makeTestService("ns2", "cluster-ip", func(svc *v1.Service) {
  564. svc.Spec.Type = v1.ServiceTypeClusterIP
  565. svc.Spec.ClusterIP = "172.16.55.4"
  566. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "p2", "UDP", 1235, 5321, 0)
  567. })
  568. fp.updateService(services[0], oneService)
  569. fp.deleteService(services[1])
  570. fp.deleteService(services[2])
  571. fp.deleteService(services[3])
  572. result = UpdateServiceMap(fp.serviceMap, fp.serviceChanges)
  573. if len(fp.serviceMap) != 1 {
  574. t.Errorf("expected service map length 1, got %v", fp.serviceMap)
  575. }
  576. if len(result.HCServiceNodePorts) != 0 {
  577. t.Errorf("expected 0 healthcheck ports, got %v", result.HCServiceNodePorts)
  578. }
  579. // All services but one were deleted. While you'd expect only the ClusterIPs
  580. // from the three deleted services here, we still have the ClusterIP for
  581. // the not-deleted service, because one of it's ServicePorts was deleted.
  582. expectedStaleUDPServices := []string{"172.16.55.10", "172.16.55.4", "172.16.55.11", "172.16.55.12"}
  583. if len(result.UDPStaleClusterIP) != len(expectedStaleUDPServices) {
  584. t.Errorf("expected stale UDP services length %d, got %v", len(expectedStaleUDPServices), result.UDPStaleClusterIP.UnsortedList())
  585. }
  586. for _, ip := range expectedStaleUDPServices {
  587. if !result.UDPStaleClusterIP.Has(ip) {
  588. t.Errorf("expected stale UDP service service %s", ip)
  589. }
  590. }
  591. }
  592. func TestBuildServiceMapServiceUpdate(t *testing.T) {
  593. fp := newFakeProxier()
  594. servicev1 := makeTestService("ns1", "svc1", func(svc *v1.Service) {
  595. svc.Spec.Type = v1.ServiceTypeClusterIP
  596. svc.Spec.ClusterIP = "172.16.55.4"
  597. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "p1", "UDP", 1234, 4321, 0)
  598. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "p2", "TCP", 1235, 5321, 0)
  599. })
  600. servicev2 := makeTestService("ns1", "svc1", func(svc *v1.Service) {
  601. svc.Spec.Type = v1.ServiceTypeLoadBalancer
  602. svc.Spec.ClusterIP = "172.16.55.4"
  603. svc.Spec.LoadBalancerIP = "5.6.7.8"
  604. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "p1", "UDP", 1234, 4321, 7002)
  605. svc.Spec.Ports = addTestPort(svc.Spec.Ports, "p2", "TCP", 1235, 5321, 7003)
  606. svc.Status.LoadBalancer = v1.LoadBalancerStatus{
  607. Ingress: []v1.LoadBalancerIngress{
  608. {IP: "10.1.2.3"},
  609. },
  610. }
  611. svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal
  612. svc.Spec.HealthCheckNodePort = 345
  613. })
  614. fp.addService(servicev1)
  615. result := UpdateServiceMap(fp.serviceMap, fp.serviceChanges)
  616. if len(fp.serviceMap) != 2 {
  617. t.Errorf("expected service map length 2, got %v", fp.serviceMap)
  618. }
  619. if len(result.HCServiceNodePorts) != 0 {
  620. t.Errorf("expected healthcheck ports length 0, got %v", result.HCServiceNodePorts)
  621. }
  622. if len(result.UDPStaleClusterIP) != 0 {
  623. // Services only added, so nothing stale yet
  624. t.Errorf("expected stale UDP services length 0, got %d", len(result.UDPStaleClusterIP))
  625. }
  626. // Change service to load-balancer
  627. fp.updateService(servicev1, servicev2)
  628. result = UpdateServiceMap(fp.serviceMap, fp.serviceChanges)
  629. if len(fp.serviceMap) != 2 {
  630. t.Errorf("expected service map length 2, got %v", fp.serviceMap)
  631. }
  632. if len(result.HCServiceNodePorts) != 1 {
  633. t.Errorf("expected healthcheck ports length 1, got %v", result.HCServiceNodePorts)
  634. }
  635. if len(result.UDPStaleClusterIP) != 0 {
  636. t.Errorf("expected stale UDP services length 0, got %v", result.UDPStaleClusterIP.UnsortedList())
  637. }
  638. // No change; make sure the service map stays the same and there are
  639. // no health-check changes
  640. fp.updateService(servicev2, servicev2)
  641. result = UpdateServiceMap(fp.serviceMap, fp.serviceChanges)
  642. if len(fp.serviceMap) != 2 {
  643. t.Errorf("expected service map length 2, got %v", fp.serviceMap)
  644. }
  645. if len(result.HCServiceNodePorts) != 1 {
  646. t.Errorf("expected healthcheck ports length 1, got %v", result.HCServiceNodePorts)
  647. }
  648. if len(result.UDPStaleClusterIP) != 0 {
  649. t.Errorf("expected stale UDP services length 0, got %v", result.UDPStaleClusterIP.UnsortedList())
  650. }
  651. // And back to ClusterIP
  652. fp.updateService(servicev2, servicev1)
  653. result = UpdateServiceMap(fp.serviceMap, fp.serviceChanges)
  654. if len(fp.serviceMap) != 2 {
  655. t.Errorf("expected service map length 2, got %v", fp.serviceMap)
  656. }
  657. if len(result.HCServiceNodePorts) != 0 {
  658. t.Errorf("expected healthcheck ports length 0, got %v", result.HCServiceNodePorts)
  659. }
  660. if len(result.UDPStaleClusterIP) != 0 {
  661. // Services only added, so nothing stale yet
  662. t.Errorf("expected stale UDP services length 0, got %d", len(result.UDPStaleClusterIP))
  663. }
  664. }