endpoints_test.go 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409
  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. "reflect"
  16. "sort"
  17. "testing"
  18. "time"
  19. "github.com/davecgh/go-spew/spew"
  20. "k8s.io/api/core/v1"
  21. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  22. "k8s.io/apimachinery/pkg/types"
  23. "k8s.io/apimachinery/pkg/util/sets"
  24. )
  25. func (proxier *FakeProxier) addEndpoints(endpoints *v1.Endpoints) {
  26. proxier.endpointsChanges.Update(nil, endpoints)
  27. }
  28. func (proxier *FakeProxier) updateEndpoints(oldEndpoints, endpoints *v1.Endpoints) {
  29. proxier.endpointsChanges.Update(oldEndpoints, endpoints)
  30. }
  31. func (proxier *FakeProxier) deleteEndpoints(endpoints *v1.Endpoints) {
  32. proxier.endpointsChanges.Update(endpoints, nil)
  33. }
  34. func TestGetLocalEndpointIPs(t *testing.T) {
  35. testCases := []struct {
  36. endpointsMap EndpointsMap
  37. expected map[types.NamespacedName]sets.String
  38. }{{
  39. // Case[0]: nothing
  40. endpointsMap: EndpointsMap{},
  41. expected: map[types.NamespacedName]sets.String{},
  42. }, {
  43. // Case[1]: unnamed port
  44. endpointsMap: EndpointsMap{
  45. makeServicePortName("ns1", "ep1", ""): []Endpoint{
  46. &BaseEndpointInfo{Endpoint: "1.1.1.1:11", IsLocal: false},
  47. },
  48. },
  49. expected: map[types.NamespacedName]sets.String{},
  50. }, {
  51. // Case[2]: unnamed port local
  52. endpointsMap: EndpointsMap{
  53. makeServicePortName("ns1", "ep1", ""): []Endpoint{
  54. &BaseEndpointInfo{Endpoint: "1.1.1.1:11", IsLocal: true},
  55. },
  56. },
  57. expected: map[types.NamespacedName]sets.String{
  58. {Namespace: "ns1", Name: "ep1"}: sets.NewString("1.1.1.1"),
  59. },
  60. }, {
  61. // Case[3]: named local and non-local ports for the same IP.
  62. endpointsMap: EndpointsMap{
  63. makeServicePortName("ns1", "ep1", "p11"): []Endpoint{
  64. &BaseEndpointInfo{Endpoint: "1.1.1.1:11", IsLocal: false},
  65. &BaseEndpointInfo{Endpoint: "1.1.1.2:11", IsLocal: true},
  66. },
  67. makeServicePortName("ns1", "ep1", "p12"): []Endpoint{
  68. &BaseEndpointInfo{Endpoint: "1.1.1.1:12", IsLocal: false},
  69. &BaseEndpointInfo{Endpoint: "1.1.1.2:12", IsLocal: true},
  70. },
  71. },
  72. expected: map[types.NamespacedName]sets.String{
  73. {Namespace: "ns1", Name: "ep1"}: sets.NewString("1.1.1.2"),
  74. },
  75. }, {
  76. // Case[4]: named local and non-local ports for different IPs.
  77. endpointsMap: EndpointsMap{
  78. makeServicePortName("ns1", "ep1", "p11"): []Endpoint{
  79. &BaseEndpointInfo{Endpoint: "1.1.1.1:11", IsLocal: false},
  80. },
  81. makeServicePortName("ns2", "ep2", "p22"): []Endpoint{
  82. &BaseEndpointInfo{Endpoint: "2.2.2.2:22", IsLocal: true},
  83. &BaseEndpointInfo{Endpoint: "2.2.2.22:22", IsLocal: true},
  84. },
  85. makeServicePortName("ns2", "ep2", "p23"): []Endpoint{
  86. &BaseEndpointInfo{Endpoint: "2.2.2.3:23", IsLocal: true},
  87. },
  88. makeServicePortName("ns4", "ep4", "p44"): []Endpoint{
  89. &BaseEndpointInfo{Endpoint: "4.4.4.4:44", IsLocal: true},
  90. &BaseEndpointInfo{Endpoint: "4.4.4.5:44", IsLocal: false},
  91. },
  92. makeServicePortName("ns4", "ep4", "p45"): []Endpoint{
  93. &BaseEndpointInfo{Endpoint: "4.4.4.6:45", IsLocal: true},
  94. },
  95. },
  96. expected: map[types.NamespacedName]sets.String{
  97. {Namespace: "ns2", Name: "ep2"}: sets.NewString("2.2.2.2", "2.2.2.22", "2.2.2.3"),
  98. {Namespace: "ns4", Name: "ep4"}: sets.NewString("4.4.4.4", "4.4.4.6"),
  99. },
  100. }}
  101. for tci, tc := range testCases {
  102. // outputs
  103. localIPs := tc.endpointsMap.getLocalEndpointIPs()
  104. if !reflect.DeepEqual(localIPs, tc.expected) {
  105. t.Errorf("[%d] expected %#v, got %#v", tci, tc.expected, localIPs)
  106. }
  107. }
  108. }
  109. func makeTestEndpoints(namespace, name string, eptFunc func(*v1.Endpoints)) *v1.Endpoints {
  110. ept := &v1.Endpoints{
  111. ObjectMeta: metav1.ObjectMeta{
  112. Name: name,
  113. Namespace: namespace,
  114. Annotations: make(map[string]string),
  115. },
  116. }
  117. eptFunc(ept)
  118. return ept
  119. }
  120. // This is a coarse test, but it offers some modicum of confidence as the code is evolved.
  121. func TestEndpointsToEndpointsMap(t *testing.T) {
  122. epTracker := NewEndpointChangeTracker("test-hostname", nil, nil, nil)
  123. trueVal := true
  124. falseVal := false
  125. testCases := []struct {
  126. desc string
  127. newEndpoints *v1.Endpoints
  128. expected map[ServicePortName][]*BaseEndpointInfo
  129. isIPv6Mode *bool
  130. }{
  131. {
  132. desc: "nothing",
  133. newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *v1.Endpoints) {}),
  134. expected: map[ServicePortName][]*BaseEndpointInfo{},
  135. },
  136. {
  137. desc: "no changes, unnamed port",
  138. newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *v1.Endpoints) {
  139. ept.Subsets = []v1.EndpointSubset{
  140. {
  141. Addresses: []v1.EndpointAddress{{
  142. IP: "1.1.1.1",
  143. }},
  144. Ports: []v1.EndpointPort{{
  145. Name: "",
  146. Port: 11,
  147. }},
  148. },
  149. }
  150. }),
  151. expected: map[ServicePortName][]*BaseEndpointInfo{
  152. makeServicePortName("ns1", "ep1", ""): {
  153. {Endpoint: "1.1.1.1:11", IsLocal: false},
  154. },
  155. },
  156. },
  157. {
  158. desc: "no changes, named port",
  159. newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *v1.Endpoints) {
  160. ept.Subsets = []v1.EndpointSubset{
  161. {
  162. Addresses: []v1.EndpointAddress{{
  163. IP: "1.1.1.1",
  164. }},
  165. Ports: []v1.EndpointPort{{
  166. Name: "port",
  167. Port: 11,
  168. }},
  169. },
  170. }
  171. }),
  172. expected: map[ServicePortName][]*BaseEndpointInfo{
  173. makeServicePortName("ns1", "ep1", "port"): {
  174. {Endpoint: "1.1.1.1:11", IsLocal: false},
  175. },
  176. },
  177. },
  178. {
  179. desc: "new port",
  180. newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *v1.Endpoints) {
  181. ept.Subsets = []v1.EndpointSubset{
  182. {
  183. Addresses: []v1.EndpointAddress{{
  184. IP: "1.1.1.1",
  185. }},
  186. Ports: []v1.EndpointPort{{
  187. Port: 11,
  188. }},
  189. },
  190. }
  191. }),
  192. expected: map[ServicePortName][]*BaseEndpointInfo{
  193. makeServicePortName("ns1", "ep1", ""): {
  194. {Endpoint: "1.1.1.1:11", IsLocal: false},
  195. },
  196. },
  197. },
  198. {
  199. desc: "remove port",
  200. newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *v1.Endpoints) {}),
  201. expected: map[ServicePortName][]*BaseEndpointInfo{},
  202. },
  203. {
  204. desc: "new IP and port",
  205. newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *v1.Endpoints) {
  206. ept.Subsets = []v1.EndpointSubset{
  207. {
  208. Addresses: []v1.EndpointAddress{{
  209. IP: "1.1.1.1",
  210. }, {
  211. IP: "2.2.2.2",
  212. }},
  213. Ports: []v1.EndpointPort{{
  214. Name: "p1",
  215. Port: 11,
  216. }, {
  217. Name: "p2",
  218. Port: 22,
  219. }},
  220. },
  221. }
  222. }),
  223. expected: map[ServicePortName][]*BaseEndpointInfo{
  224. makeServicePortName("ns1", "ep1", "p1"): {
  225. {Endpoint: "1.1.1.1:11", IsLocal: false},
  226. {Endpoint: "2.2.2.2:11", IsLocal: false},
  227. },
  228. makeServicePortName("ns1", "ep1", "p2"): {
  229. {Endpoint: "1.1.1.1:22", IsLocal: false},
  230. {Endpoint: "2.2.2.2:22", IsLocal: false},
  231. },
  232. },
  233. },
  234. {
  235. desc: "remove IP and port",
  236. newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *v1.Endpoints) {
  237. ept.Subsets = []v1.EndpointSubset{
  238. {
  239. Addresses: []v1.EndpointAddress{{
  240. IP: "1.1.1.1",
  241. }},
  242. Ports: []v1.EndpointPort{{
  243. Name: "p1",
  244. Port: 11,
  245. }},
  246. },
  247. }
  248. }),
  249. expected: map[ServicePortName][]*BaseEndpointInfo{
  250. makeServicePortName("ns1", "ep1", "p1"): {
  251. {Endpoint: "1.1.1.1:11", IsLocal: false},
  252. },
  253. },
  254. },
  255. {
  256. desc: "rename port",
  257. newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *v1.Endpoints) {
  258. ept.Subsets = []v1.EndpointSubset{
  259. {
  260. Addresses: []v1.EndpointAddress{{
  261. IP: "1.1.1.1",
  262. }},
  263. Ports: []v1.EndpointPort{{
  264. Name: "p2",
  265. Port: 11,
  266. }},
  267. },
  268. }
  269. }),
  270. expected: map[ServicePortName][]*BaseEndpointInfo{
  271. makeServicePortName("ns1", "ep1", "p2"): {
  272. {Endpoint: "1.1.1.1:11", IsLocal: false},
  273. },
  274. },
  275. },
  276. {
  277. desc: "renumber port",
  278. newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *v1.Endpoints) {
  279. ept.Subsets = []v1.EndpointSubset{
  280. {
  281. Addresses: []v1.EndpointAddress{{
  282. IP: "1.1.1.1",
  283. }},
  284. Ports: []v1.EndpointPort{{
  285. Name: "p1",
  286. Port: 22,
  287. }},
  288. },
  289. }
  290. }),
  291. expected: map[ServicePortName][]*BaseEndpointInfo{
  292. makeServicePortName("ns1", "ep1", "p1"): {
  293. {Endpoint: "1.1.1.1:22", IsLocal: false},
  294. },
  295. },
  296. },
  297. {
  298. desc: "should omit IPv6 address in IPv4 mode",
  299. newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *v1.Endpoints) {
  300. ept.Subsets = []v1.EndpointSubset{
  301. {
  302. Addresses: []v1.EndpointAddress{{
  303. IP: "1.1.1.1",
  304. }, {
  305. IP: "2001:db8:85a3:0:0:8a2e:370:7334",
  306. }},
  307. Ports: []v1.EndpointPort{{
  308. Name: "p1",
  309. Port: 11,
  310. }, {
  311. Name: "p2",
  312. Port: 22,
  313. }},
  314. },
  315. }
  316. }),
  317. expected: map[ServicePortName][]*BaseEndpointInfo{
  318. makeServicePortName("ns1", "ep1", "p1"): {
  319. {Endpoint: "1.1.1.1:11", IsLocal: false},
  320. },
  321. makeServicePortName("ns1", "ep1", "p2"): {
  322. {Endpoint: "1.1.1.1:22", IsLocal: false},
  323. },
  324. },
  325. isIPv6Mode: &falseVal,
  326. },
  327. {
  328. desc: "should omit IPv4 address in IPv6 mode",
  329. newEndpoints: makeTestEndpoints("ns1", "ep1", func(ept *v1.Endpoints) {
  330. ept.Subsets = []v1.EndpointSubset{
  331. {
  332. Addresses: []v1.EndpointAddress{{
  333. IP: "1.1.1.1",
  334. }, {
  335. IP: "2001:db8:85a3:0:0:8a2e:370:7334",
  336. }},
  337. Ports: []v1.EndpointPort{{
  338. Name: "p1",
  339. Port: 11,
  340. }, {
  341. Name: "p2",
  342. Port: 22,
  343. }},
  344. },
  345. }
  346. }),
  347. expected: map[ServicePortName][]*BaseEndpointInfo{
  348. makeServicePortName("ns1", "ep1", "p1"): {
  349. {Endpoint: "[2001:db8:85a3:0:0:8a2e:370:7334]:11", IsLocal: false},
  350. },
  351. makeServicePortName("ns1", "ep1", "p2"): {
  352. {Endpoint: "[2001:db8:85a3:0:0:8a2e:370:7334]:22", IsLocal: false},
  353. },
  354. },
  355. isIPv6Mode: &trueVal,
  356. },
  357. }
  358. for _, tc := range testCases {
  359. epTracker.isIPv6Mode = tc.isIPv6Mode
  360. // outputs
  361. newEndpoints := epTracker.endpointsToEndpointsMap(tc.newEndpoints)
  362. if len(newEndpoints) != len(tc.expected) {
  363. t.Errorf("[%s] expected %d new, got %d: %v", tc.desc, len(tc.expected), len(newEndpoints), spew.Sdump(newEndpoints))
  364. }
  365. for x := range tc.expected {
  366. if len(newEndpoints[x]) != len(tc.expected[x]) {
  367. t.Errorf("[%s] expected %d endpoints for %v, got %d", tc.desc, len(tc.expected[x]), x, len(newEndpoints[x]))
  368. } else {
  369. for i := range newEndpoints[x] {
  370. ep := newEndpoints[x][i].(*BaseEndpointInfo)
  371. if *ep != *(tc.expected[x][i]) {
  372. t.Errorf("[%s] expected new[%v][%d] to be %v, got %v", tc.desc, x, i, tc.expected[x][i], *ep)
  373. }
  374. }
  375. }
  376. }
  377. }
  378. }
  379. func TestUpdateEndpointsMap(t *testing.T) {
  380. var nodeName = testHostname
  381. emptyEndpoint := func(ept *v1.Endpoints) {
  382. ept.Subsets = []v1.EndpointSubset{}
  383. }
  384. unnamedPort := func(ept *v1.Endpoints) {
  385. ept.Subsets = []v1.EndpointSubset{{
  386. Addresses: []v1.EndpointAddress{{
  387. IP: "1.1.1.1",
  388. }},
  389. Ports: []v1.EndpointPort{{
  390. Port: 11,
  391. }},
  392. }}
  393. }
  394. unnamedPortLocal := func(ept *v1.Endpoints) {
  395. ept.Subsets = []v1.EndpointSubset{{
  396. Addresses: []v1.EndpointAddress{{
  397. IP: "1.1.1.1",
  398. NodeName: &nodeName,
  399. }},
  400. Ports: []v1.EndpointPort{{
  401. Port: 11,
  402. }},
  403. }}
  404. }
  405. namedPortLocal := func(ept *v1.Endpoints) {
  406. ept.Subsets = []v1.EndpointSubset{{
  407. Addresses: []v1.EndpointAddress{{
  408. IP: "1.1.1.1",
  409. NodeName: &nodeName,
  410. }},
  411. Ports: []v1.EndpointPort{{
  412. Name: "p11",
  413. Port: 11,
  414. }},
  415. }}
  416. }
  417. namedPort := func(ept *v1.Endpoints) {
  418. ept.Subsets = []v1.EndpointSubset{{
  419. Addresses: []v1.EndpointAddress{{
  420. IP: "1.1.1.1",
  421. }},
  422. Ports: []v1.EndpointPort{{
  423. Name: "p11",
  424. Port: 11,
  425. }},
  426. }}
  427. }
  428. namedPortRenamed := func(ept *v1.Endpoints) {
  429. ept.Subsets = []v1.EndpointSubset{{
  430. Addresses: []v1.EndpointAddress{{
  431. IP: "1.1.1.1",
  432. }},
  433. Ports: []v1.EndpointPort{{
  434. Name: "p11-2",
  435. Port: 11,
  436. }},
  437. }}
  438. }
  439. namedPortRenumbered := func(ept *v1.Endpoints) {
  440. ept.Subsets = []v1.EndpointSubset{{
  441. Addresses: []v1.EndpointAddress{{
  442. IP: "1.1.1.1",
  443. }},
  444. Ports: []v1.EndpointPort{{
  445. Name: "p11",
  446. Port: 22,
  447. }},
  448. }}
  449. }
  450. namedPortsLocalNoLocal := func(ept *v1.Endpoints) {
  451. ept.Subsets = []v1.EndpointSubset{{
  452. Addresses: []v1.EndpointAddress{{
  453. IP: "1.1.1.1",
  454. }, {
  455. IP: "1.1.1.2",
  456. NodeName: &nodeName,
  457. }},
  458. Ports: []v1.EndpointPort{{
  459. Name: "p11",
  460. Port: 11,
  461. }, {
  462. Name: "p12",
  463. Port: 12,
  464. }},
  465. }}
  466. }
  467. multipleSubsets := func(ept *v1.Endpoints) {
  468. ept.Subsets = []v1.EndpointSubset{{
  469. Addresses: []v1.EndpointAddress{{
  470. IP: "1.1.1.1",
  471. }},
  472. Ports: []v1.EndpointPort{{
  473. Name: "p11",
  474. Port: 11,
  475. }},
  476. }, {
  477. Addresses: []v1.EndpointAddress{{
  478. IP: "1.1.1.2",
  479. }},
  480. Ports: []v1.EndpointPort{{
  481. Name: "p12",
  482. Port: 12,
  483. }},
  484. }}
  485. }
  486. multipleSubsetsWithLocal := func(ept *v1.Endpoints) {
  487. ept.Subsets = []v1.EndpointSubset{{
  488. Addresses: []v1.EndpointAddress{{
  489. IP: "1.1.1.1",
  490. }},
  491. Ports: []v1.EndpointPort{{
  492. Name: "p11",
  493. Port: 11,
  494. }},
  495. }, {
  496. Addresses: []v1.EndpointAddress{{
  497. IP: "1.1.1.2",
  498. NodeName: &nodeName,
  499. }},
  500. Ports: []v1.EndpointPort{{
  501. Name: "p12",
  502. Port: 12,
  503. }},
  504. }}
  505. }
  506. multipleSubsetsMultiplePortsLocal := func(ept *v1.Endpoints) {
  507. ept.Subsets = []v1.EndpointSubset{{
  508. Addresses: []v1.EndpointAddress{{
  509. IP: "1.1.1.1",
  510. NodeName: &nodeName,
  511. }},
  512. Ports: []v1.EndpointPort{{
  513. Name: "p11",
  514. Port: 11,
  515. }, {
  516. Name: "p12",
  517. Port: 12,
  518. }},
  519. }, {
  520. Addresses: []v1.EndpointAddress{{
  521. IP: "1.1.1.3",
  522. }},
  523. Ports: []v1.EndpointPort{{
  524. Name: "p13",
  525. Port: 13,
  526. }},
  527. }}
  528. }
  529. multipleSubsetsIPsPorts1 := func(ept *v1.Endpoints) {
  530. ept.Subsets = []v1.EndpointSubset{{
  531. Addresses: []v1.EndpointAddress{{
  532. IP: "1.1.1.1",
  533. }, {
  534. IP: "1.1.1.2",
  535. NodeName: &nodeName,
  536. }},
  537. Ports: []v1.EndpointPort{{
  538. Name: "p11",
  539. Port: 11,
  540. }, {
  541. Name: "p12",
  542. Port: 12,
  543. }},
  544. }, {
  545. Addresses: []v1.EndpointAddress{{
  546. IP: "1.1.1.3",
  547. }, {
  548. IP: "1.1.1.4",
  549. NodeName: &nodeName,
  550. }},
  551. Ports: []v1.EndpointPort{{
  552. Name: "p13",
  553. Port: 13,
  554. }, {
  555. Name: "p14",
  556. Port: 14,
  557. }},
  558. }}
  559. }
  560. multipleSubsetsIPsPorts2 := func(ept *v1.Endpoints) {
  561. ept.Subsets = []v1.EndpointSubset{{
  562. Addresses: []v1.EndpointAddress{{
  563. IP: "2.2.2.1",
  564. }, {
  565. IP: "2.2.2.2",
  566. NodeName: &nodeName,
  567. }},
  568. Ports: []v1.EndpointPort{{
  569. Name: "p21",
  570. Port: 21,
  571. }, {
  572. Name: "p22",
  573. Port: 22,
  574. }},
  575. }}
  576. }
  577. complexBefore1 := func(ept *v1.Endpoints) {
  578. ept.Subsets = []v1.EndpointSubset{{
  579. Addresses: []v1.EndpointAddress{{
  580. IP: "1.1.1.1",
  581. }},
  582. Ports: []v1.EndpointPort{{
  583. Name: "p11",
  584. Port: 11,
  585. }},
  586. }}
  587. }
  588. complexBefore2 := func(ept *v1.Endpoints) {
  589. ept.Subsets = []v1.EndpointSubset{{
  590. Addresses: []v1.EndpointAddress{{
  591. IP: "2.2.2.2",
  592. NodeName: &nodeName,
  593. }, {
  594. IP: "2.2.2.22",
  595. NodeName: &nodeName,
  596. }},
  597. Ports: []v1.EndpointPort{{
  598. Name: "p22",
  599. Port: 22,
  600. }},
  601. }, {
  602. Addresses: []v1.EndpointAddress{{
  603. IP: "2.2.2.3",
  604. NodeName: &nodeName,
  605. }},
  606. Ports: []v1.EndpointPort{{
  607. Name: "p23",
  608. Port: 23,
  609. }},
  610. }}
  611. }
  612. complexBefore4 := func(ept *v1.Endpoints) {
  613. ept.Subsets = []v1.EndpointSubset{{
  614. Addresses: []v1.EndpointAddress{{
  615. IP: "4.4.4.4",
  616. NodeName: &nodeName,
  617. }, {
  618. IP: "4.4.4.5",
  619. NodeName: &nodeName,
  620. }},
  621. Ports: []v1.EndpointPort{{
  622. Name: "p44",
  623. Port: 44,
  624. }},
  625. }, {
  626. Addresses: []v1.EndpointAddress{{
  627. IP: "4.4.4.6",
  628. NodeName: &nodeName,
  629. }},
  630. Ports: []v1.EndpointPort{{
  631. Name: "p45",
  632. Port: 45,
  633. }},
  634. }}
  635. }
  636. complexAfter1 := func(ept *v1.Endpoints) {
  637. ept.Subsets = []v1.EndpointSubset{{
  638. Addresses: []v1.EndpointAddress{{
  639. IP: "1.1.1.1",
  640. }, {
  641. IP: "1.1.1.11",
  642. }},
  643. Ports: []v1.EndpointPort{{
  644. Name: "p11",
  645. Port: 11,
  646. }},
  647. }, {
  648. Addresses: []v1.EndpointAddress{{
  649. IP: "1.1.1.2",
  650. }},
  651. Ports: []v1.EndpointPort{{
  652. Name: "p12",
  653. Port: 12,
  654. }, {
  655. Name: "p122",
  656. Port: 122,
  657. }},
  658. }}
  659. }
  660. complexAfter3 := func(ept *v1.Endpoints) {
  661. ept.Subsets = []v1.EndpointSubset{{
  662. Addresses: []v1.EndpointAddress{{
  663. IP: "3.3.3.3",
  664. }},
  665. Ports: []v1.EndpointPort{{
  666. Name: "p33",
  667. Port: 33,
  668. }},
  669. }}
  670. }
  671. complexAfter4 := func(ept *v1.Endpoints) {
  672. ept.Subsets = []v1.EndpointSubset{{
  673. Addresses: []v1.EndpointAddress{{
  674. IP: "4.4.4.4",
  675. NodeName: &nodeName,
  676. }},
  677. Ports: []v1.EndpointPort{{
  678. Name: "p44",
  679. Port: 44,
  680. }},
  681. }}
  682. }
  683. testCases := []struct {
  684. // previousEndpoints and currentEndpoints are used to call appropriate
  685. // handlers OnEndpoints* (based on whether corresponding values are nil
  686. // or non-nil) and must be of equal length.
  687. previousEndpoints []*v1.Endpoints
  688. currentEndpoints []*v1.Endpoints
  689. oldEndpoints map[ServicePortName][]*BaseEndpointInfo
  690. expectedResult map[ServicePortName][]*BaseEndpointInfo
  691. expectedStaleEndpoints []ServiceEndpoint
  692. expectedStaleServiceNames map[ServicePortName]bool
  693. expectedHealthchecks map[types.NamespacedName]int
  694. }{{
  695. // Case[0]: nothing
  696. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{},
  697. expectedResult: map[ServicePortName][]*BaseEndpointInfo{},
  698. expectedStaleEndpoints: []ServiceEndpoint{},
  699. expectedStaleServiceNames: map[ServicePortName]bool{},
  700. expectedHealthchecks: map[types.NamespacedName]int{},
  701. }, {
  702. // Case[1]: no change, unnamed port
  703. previousEndpoints: []*v1.Endpoints{
  704. makeTestEndpoints("ns1", "ep1", unnamedPort),
  705. },
  706. currentEndpoints: []*v1.Endpoints{
  707. makeTestEndpoints("ns1", "ep1", unnamedPort),
  708. },
  709. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  710. makeServicePortName("ns1", "ep1", ""): {
  711. {Endpoint: "1.1.1.1:11", IsLocal: false},
  712. },
  713. },
  714. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  715. makeServicePortName("ns1", "ep1", ""): {
  716. {Endpoint: "1.1.1.1:11", IsLocal: false},
  717. },
  718. },
  719. expectedStaleEndpoints: []ServiceEndpoint{},
  720. expectedStaleServiceNames: map[ServicePortName]bool{},
  721. expectedHealthchecks: map[types.NamespacedName]int{},
  722. }, {
  723. // Case[2]: no change, named port, local
  724. previousEndpoints: []*v1.Endpoints{
  725. makeTestEndpoints("ns1", "ep1", namedPortLocal),
  726. },
  727. currentEndpoints: []*v1.Endpoints{
  728. makeTestEndpoints("ns1", "ep1", namedPortLocal),
  729. },
  730. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  731. makeServicePortName("ns1", "ep1", "p11"): {
  732. {Endpoint: "1.1.1.1:11", IsLocal: true},
  733. },
  734. },
  735. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  736. makeServicePortName("ns1", "ep1", "p11"): {
  737. {Endpoint: "1.1.1.1:11", IsLocal: true},
  738. },
  739. },
  740. expectedStaleEndpoints: []ServiceEndpoint{},
  741. expectedStaleServiceNames: map[ServicePortName]bool{},
  742. expectedHealthchecks: map[types.NamespacedName]int{
  743. makeNSN("ns1", "ep1"): 1,
  744. },
  745. }, {
  746. // Case[3]: no change, multiple subsets
  747. previousEndpoints: []*v1.Endpoints{
  748. makeTestEndpoints("ns1", "ep1", multipleSubsets),
  749. },
  750. currentEndpoints: []*v1.Endpoints{
  751. makeTestEndpoints("ns1", "ep1", multipleSubsets),
  752. },
  753. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  754. makeServicePortName("ns1", "ep1", "p11"): {
  755. {Endpoint: "1.1.1.1:11", IsLocal: false},
  756. },
  757. makeServicePortName("ns1", "ep1", "p12"): {
  758. {Endpoint: "1.1.1.2:12", IsLocal: false},
  759. },
  760. },
  761. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  762. makeServicePortName("ns1", "ep1", "p11"): {
  763. {Endpoint: "1.1.1.1:11", IsLocal: false},
  764. },
  765. makeServicePortName("ns1", "ep1", "p12"): {
  766. {Endpoint: "1.1.1.2:12", IsLocal: false},
  767. },
  768. },
  769. expectedStaleEndpoints: []ServiceEndpoint{},
  770. expectedStaleServiceNames: map[ServicePortName]bool{},
  771. expectedHealthchecks: map[types.NamespacedName]int{},
  772. }, {
  773. // Case[4]: no change, multiple subsets, multiple ports, local
  774. previousEndpoints: []*v1.Endpoints{
  775. makeTestEndpoints("ns1", "ep1", multipleSubsetsMultiplePortsLocal),
  776. },
  777. currentEndpoints: []*v1.Endpoints{
  778. makeTestEndpoints("ns1", "ep1", multipleSubsetsMultiplePortsLocal),
  779. },
  780. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  781. makeServicePortName("ns1", "ep1", "p11"): {
  782. {Endpoint: "1.1.1.1:11", IsLocal: true},
  783. },
  784. makeServicePortName("ns1", "ep1", "p12"): {
  785. {Endpoint: "1.1.1.1:12", IsLocal: true},
  786. },
  787. makeServicePortName("ns1", "ep1", "p13"): {
  788. {Endpoint: "1.1.1.3:13", IsLocal: false},
  789. },
  790. },
  791. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  792. makeServicePortName("ns1", "ep1", "p11"): {
  793. {Endpoint: "1.1.1.1:11", IsLocal: true},
  794. },
  795. makeServicePortName("ns1", "ep1", "p12"): {
  796. {Endpoint: "1.1.1.1:12", IsLocal: true},
  797. },
  798. makeServicePortName("ns1", "ep1", "p13"): {
  799. {Endpoint: "1.1.1.3:13", IsLocal: false},
  800. },
  801. },
  802. expectedStaleEndpoints: []ServiceEndpoint{},
  803. expectedStaleServiceNames: map[ServicePortName]bool{},
  804. expectedHealthchecks: map[types.NamespacedName]int{
  805. makeNSN("ns1", "ep1"): 1,
  806. },
  807. }, {
  808. // Case[5]: no change, multiple endpoints, subsets, IPs, and ports
  809. previousEndpoints: []*v1.Endpoints{
  810. makeTestEndpoints("ns1", "ep1", multipleSubsetsIPsPorts1),
  811. makeTestEndpoints("ns2", "ep2", multipleSubsetsIPsPorts2),
  812. },
  813. currentEndpoints: []*v1.Endpoints{
  814. makeTestEndpoints("ns1", "ep1", multipleSubsetsIPsPorts1),
  815. makeTestEndpoints("ns2", "ep2", multipleSubsetsIPsPorts2),
  816. },
  817. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  818. makeServicePortName("ns1", "ep1", "p11"): {
  819. {Endpoint: "1.1.1.1:11", IsLocal: false},
  820. {Endpoint: "1.1.1.2:11", IsLocal: true},
  821. },
  822. makeServicePortName("ns1", "ep1", "p12"): {
  823. {Endpoint: "1.1.1.1:12", IsLocal: false},
  824. {Endpoint: "1.1.1.2:12", IsLocal: true},
  825. },
  826. makeServicePortName("ns1", "ep1", "p13"): {
  827. {Endpoint: "1.1.1.3:13", IsLocal: false},
  828. {Endpoint: "1.1.1.4:13", IsLocal: true},
  829. },
  830. makeServicePortName("ns1", "ep1", "p14"): {
  831. {Endpoint: "1.1.1.3:14", IsLocal: false},
  832. {Endpoint: "1.1.1.4:14", IsLocal: true},
  833. },
  834. makeServicePortName("ns2", "ep2", "p21"): {
  835. {Endpoint: "2.2.2.1:21", IsLocal: false},
  836. {Endpoint: "2.2.2.2:21", IsLocal: true},
  837. },
  838. makeServicePortName("ns2", "ep2", "p22"): {
  839. {Endpoint: "2.2.2.1:22", IsLocal: false},
  840. {Endpoint: "2.2.2.2:22", IsLocal: true},
  841. },
  842. },
  843. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  844. makeServicePortName("ns1", "ep1", "p11"): {
  845. {Endpoint: "1.1.1.1:11", IsLocal: false},
  846. {Endpoint: "1.1.1.2:11", IsLocal: true},
  847. },
  848. makeServicePortName("ns1", "ep1", "p12"): {
  849. {Endpoint: "1.1.1.1:12", IsLocal: false},
  850. {Endpoint: "1.1.1.2:12", IsLocal: true},
  851. },
  852. makeServicePortName("ns1", "ep1", "p13"): {
  853. {Endpoint: "1.1.1.3:13", IsLocal: false},
  854. {Endpoint: "1.1.1.4:13", IsLocal: true},
  855. },
  856. makeServicePortName("ns1", "ep1", "p14"): {
  857. {Endpoint: "1.1.1.3:14", IsLocal: false},
  858. {Endpoint: "1.1.1.4:14", IsLocal: true},
  859. },
  860. makeServicePortName("ns2", "ep2", "p21"): {
  861. {Endpoint: "2.2.2.1:21", IsLocal: false},
  862. {Endpoint: "2.2.2.2:21", IsLocal: true},
  863. },
  864. makeServicePortName("ns2", "ep2", "p22"): {
  865. {Endpoint: "2.2.2.1:22", IsLocal: false},
  866. {Endpoint: "2.2.2.2:22", IsLocal: true},
  867. },
  868. },
  869. expectedStaleEndpoints: []ServiceEndpoint{},
  870. expectedStaleServiceNames: map[ServicePortName]bool{},
  871. expectedHealthchecks: map[types.NamespacedName]int{
  872. makeNSN("ns1", "ep1"): 2,
  873. makeNSN("ns2", "ep2"): 1,
  874. },
  875. }, {
  876. // Case[6]: add an Endpoints
  877. previousEndpoints: []*v1.Endpoints{
  878. nil,
  879. },
  880. currentEndpoints: []*v1.Endpoints{
  881. makeTestEndpoints("ns1", "ep1", unnamedPortLocal),
  882. },
  883. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{},
  884. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  885. makeServicePortName("ns1", "ep1", ""): {
  886. {Endpoint: "1.1.1.1:11", IsLocal: true},
  887. },
  888. },
  889. expectedStaleEndpoints: []ServiceEndpoint{},
  890. expectedStaleServiceNames: map[ServicePortName]bool{
  891. makeServicePortName("ns1", "ep1", ""): true,
  892. },
  893. expectedHealthchecks: map[types.NamespacedName]int{
  894. makeNSN("ns1", "ep1"): 1,
  895. },
  896. }, {
  897. // Case[7]: remove an Endpoints
  898. previousEndpoints: []*v1.Endpoints{
  899. makeTestEndpoints("ns1", "ep1", unnamedPortLocal),
  900. },
  901. currentEndpoints: []*v1.Endpoints{
  902. nil,
  903. },
  904. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  905. makeServicePortName("ns1", "ep1", ""): {
  906. {Endpoint: "1.1.1.1:11", IsLocal: true},
  907. },
  908. },
  909. expectedResult: map[ServicePortName][]*BaseEndpointInfo{},
  910. expectedStaleEndpoints: []ServiceEndpoint{{
  911. Endpoint: "1.1.1.1:11",
  912. ServicePortName: makeServicePortName("ns1", "ep1", ""),
  913. }},
  914. expectedStaleServiceNames: map[ServicePortName]bool{},
  915. expectedHealthchecks: map[types.NamespacedName]int{},
  916. }, {
  917. // Case[8]: add an IP and port
  918. previousEndpoints: []*v1.Endpoints{
  919. makeTestEndpoints("ns1", "ep1", namedPort),
  920. },
  921. currentEndpoints: []*v1.Endpoints{
  922. makeTestEndpoints("ns1", "ep1", namedPortsLocalNoLocal),
  923. },
  924. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  925. makeServicePortName("ns1", "ep1", "p11"): {
  926. {Endpoint: "1.1.1.1:11", IsLocal: false},
  927. },
  928. },
  929. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  930. makeServicePortName("ns1", "ep1", "p11"): {
  931. {Endpoint: "1.1.1.1:11", IsLocal: false},
  932. {Endpoint: "1.1.1.2:11", IsLocal: true},
  933. },
  934. makeServicePortName("ns1", "ep1", "p12"): {
  935. {Endpoint: "1.1.1.1:12", IsLocal: false},
  936. {Endpoint: "1.1.1.2:12", IsLocal: true},
  937. },
  938. },
  939. expectedStaleEndpoints: []ServiceEndpoint{},
  940. expectedStaleServiceNames: map[ServicePortName]bool{
  941. makeServicePortName("ns1", "ep1", "p12"): true,
  942. },
  943. expectedHealthchecks: map[types.NamespacedName]int{
  944. makeNSN("ns1", "ep1"): 1,
  945. },
  946. }, {
  947. // Case[9]: remove an IP and port
  948. previousEndpoints: []*v1.Endpoints{
  949. makeTestEndpoints("ns1", "ep1", namedPortsLocalNoLocal),
  950. },
  951. currentEndpoints: []*v1.Endpoints{
  952. makeTestEndpoints("ns1", "ep1", namedPort),
  953. },
  954. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  955. makeServicePortName("ns1", "ep1", "p11"): {
  956. {Endpoint: "1.1.1.1:11", IsLocal: false},
  957. {Endpoint: "1.1.1.2:11", IsLocal: true},
  958. },
  959. makeServicePortName("ns1", "ep1", "p12"): {
  960. {Endpoint: "1.1.1.1:12", IsLocal: false},
  961. {Endpoint: "1.1.1.2:12", IsLocal: true},
  962. },
  963. },
  964. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  965. makeServicePortName("ns1", "ep1", "p11"): {
  966. {Endpoint: "1.1.1.1:11", IsLocal: false},
  967. },
  968. },
  969. expectedStaleEndpoints: []ServiceEndpoint{{
  970. Endpoint: "1.1.1.2:11",
  971. ServicePortName: makeServicePortName("ns1", "ep1", "p11"),
  972. }, {
  973. Endpoint: "1.1.1.1:12",
  974. ServicePortName: makeServicePortName("ns1", "ep1", "p12"),
  975. }, {
  976. Endpoint: "1.1.1.2:12",
  977. ServicePortName: makeServicePortName("ns1", "ep1", "p12"),
  978. }},
  979. expectedStaleServiceNames: map[ServicePortName]bool{},
  980. expectedHealthchecks: map[types.NamespacedName]int{},
  981. }, {
  982. // Case[10]: add a subset
  983. previousEndpoints: []*v1.Endpoints{
  984. makeTestEndpoints("ns1", "ep1", namedPort),
  985. },
  986. currentEndpoints: []*v1.Endpoints{
  987. makeTestEndpoints("ns1", "ep1", multipleSubsetsWithLocal),
  988. },
  989. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  990. makeServicePortName("ns1", "ep1", "p11"): {
  991. {Endpoint: "1.1.1.1:11", IsLocal: false},
  992. },
  993. },
  994. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  995. makeServicePortName("ns1", "ep1", "p11"): {
  996. {Endpoint: "1.1.1.1:11", IsLocal: false},
  997. },
  998. makeServicePortName("ns1", "ep1", "p12"): {
  999. {Endpoint: "1.1.1.2:12", IsLocal: true},
  1000. },
  1001. },
  1002. expectedStaleEndpoints: []ServiceEndpoint{},
  1003. expectedStaleServiceNames: map[ServicePortName]bool{
  1004. makeServicePortName("ns1", "ep1", "p12"): true,
  1005. },
  1006. expectedHealthchecks: map[types.NamespacedName]int{
  1007. makeNSN("ns1", "ep1"): 1,
  1008. },
  1009. }, {
  1010. // Case[11]: remove a subset
  1011. previousEndpoints: []*v1.Endpoints{
  1012. makeTestEndpoints("ns1", "ep1", multipleSubsets),
  1013. },
  1014. currentEndpoints: []*v1.Endpoints{
  1015. makeTestEndpoints("ns1", "ep1", namedPort),
  1016. },
  1017. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  1018. makeServicePortName("ns1", "ep1", "p11"): {
  1019. {Endpoint: "1.1.1.1:11", IsLocal: false},
  1020. },
  1021. makeServicePortName("ns1", "ep1", "p12"): {
  1022. {Endpoint: "1.1.1.2:12", IsLocal: false},
  1023. },
  1024. },
  1025. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  1026. makeServicePortName("ns1", "ep1", "p11"): {
  1027. {Endpoint: "1.1.1.1:11", IsLocal: false},
  1028. },
  1029. },
  1030. expectedStaleEndpoints: []ServiceEndpoint{{
  1031. Endpoint: "1.1.1.2:12",
  1032. ServicePortName: makeServicePortName("ns1", "ep1", "p12"),
  1033. }},
  1034. expectedStaleServiceNames: map[ServicePortName]bool{},
  1035. expectedHealthchecks: map[types.NamespacedName]int{},
  1036. }, {
  1037. // Case[12]: rename a port
  1038. previousEndpoints: []*v1.Endpoints{
  1039. makeTestEndpoints("ns1", "ep1", namedPort),
  1040. },
  1041. currentEndpoints: []*v1.Endpoints{
  1042. makeTestEndpoints("ns1", "ep1", namedPortRenamed),
  1043. },
  1044. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  1045. makeServicePortName("ns1", "ep1", "p11"): {
  1046. {Endpoint: "1.1.1.1:11", IsLocal: false},
  1047. },
  1048. },
  1049. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  1050. makeServicePortName("ns1", "ep1", "p11-2"): {
  1051. {Endpoint: "1.1.1.1:11", IsLocal: false},
  1052. },
  1053. },
  1054. expectedStaleEndpoints: []ServiceEndpoint{{
  1055. Endpoint: "1.1.1.1:11",
  1056. ServicePortName: makeServicePortName("ns1", "ep1", "p11"),
  1057. }},
  1058. expectedStaleServiceNames: map[ServicePortName]bool{
  1059. makeServicePortName("ns1", "ep1", "p11-2"): true,
  1060. },
  1061. expectedHealthchecks: map[types.NamespacedName]int{},
  1062. }, {
  1063. // Case[13]: renumber a port
  1064. previousEndpoints: []*v1.Endpoints{
  1065. makeTestEndpoints("ns1", "ep1", namedPort),
  1066. },
  1067. currentEndpoints: []*v1.Endpoints{
  1068. makeTestEndpoints("ns1", "ep1", namedPortRenumbered),
  1069. },
  1070. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  1071. makeServicePortName("ns1", "ep1", "p11"): {
  1072. {Endpoint: "1.1.1.1:11", IsLocal: false},
  1073. },
  1074. },
  1075. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  1076. makeServicePortName("ns1", "ep1", "p11"): {
  1077. {Endpoint: "1.1.1.1:22", IsLocal: false},
  1078. },
  1079. },
  1080. expectedStaleEndpoints: []ServiceEndpoint{{
  1081. Endpoint: "1.1.1.1:11",
  1082. ServicePortName: makeServicePortName("ns1", "ep1", "p11"),
  1083. }},
  1084. expectedStaleServiceNames: map[ServicePortName]bool{},
  1085. expectedHealthchecks: map[types.NamespacedName]int{},
  1086. }, {
  1087. // Case[14]: complex add and remove
  1088. previousEndpoints: []*v1.Endpoints{
  1089. makeTestEndpoints("ns1", "ep1", complexBefore1),
  1090. makeTestEndpoints("ns2", "ep2", complexBefore2),
  1091. nil,
  1092. makeTestEndpoints("ns4", "ep4", complexBefore4),
  1093. },
  1094. currentEndpoints: []*v1.Endpoints{
  1095. makeTestEndpoints("ns1", "ep1", complexAfter1),
  1096. nil,
  1097. makeTestEndpoints("ns3", "ep3", complexAfter3),
  1098. makeTestEndpoints("ns4", "ep4", complexAfter4),
  1099. },
  1100. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{
  1101. makeServicePortName("ns1", "ep1", "p11"): {
  1102. {Endpoint: "1.1.1.1:11", IsLocal: false},
  1103. },
  1104. makeServicePortName("ns2", "ep2", "p22"): {
  1105. {Endpoint: "2.2.2.2:22", IsLocal: true},
  1106. {Endpoint: "2.2.2.22:22", IsLocal: true},
  1107. },
  1108. makeServicePortName("ns2", "ep2", "p23"): {
  1109. {Endpoint: "2.2.2.3:23", IsLocal: true},
  1110. },
  1111. makeServicePortName("ns4", "ep4", "p44"): {
  1112. {Endpoint: "4.4.4.4:44", IsLocal: true},
  1113. {Endpoint: "4.4.4.5:44", IsLocal: true},
  1114. },
  1115. makeServicePortName("ns4", "ep4", "p45"): {
  1116. {Endpoint: "4.4.4.6:45", IsLocal: true},
  1117. },
  1118. },
  1119. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  1120. makeServicePortName("ns1", "ep1", "p11"): {
  1121. {Endpoint: "1.1.1.1:11", IsLocal: false},
  1122. {Endpoint: "1.1.1.11:11", IsLocal: false},
  1123. },
  1124. makeServicePortName("ns1", "ep1", "p12"): {
  1125. {Endpoint: "1.1.1.2:12", IsLocal: false},
  1126. },
  1127. makeServicePortName("ns1", "ep1", "p122"): {
  1128. {Endpoint: "1.1.1.2:122", IsLocal: false},
  1129. },
  1130. makeServicePortName("ns3", "ep3", "p33"): {
  1131. {Endpoint: "3.3.3.3:33", IsLocal: false},
  1132. },
  1133. makeServicePortName("ns4", "ep4", "p44"): {
  1134. {Endpoint: "4.4.4.4:44", IsLocal: true},
  1135. },
  1136. },
  1137. expectedStaleEndpoints: []ServiceEndpoint{{
  1138. Endpoint: "2.2.2.2:22",
  1139. ServicePortName: makeServicePortName("ns2", "ep2", "p22"),
  1140. }, {
  1141. Endpoint: "2.2.2.22:22",
  1142. ServicePortName: makeServicePortName("ns2", "ep2", "p22"),
  1143. }, {
  1144. Endpoint: "2.2.2.3:23",
  1145. ServicePortName: makeServicePortName("ns2", "ep2", "p23"),
  1146. }, {
  1147. Endpoint: "4.4.4.5:44",
  1148. ServicePortName: makeServicePortName("ns4", "ep4", "p44"),
  1149. }, {
  1150. Endpoint: "4.4.4.6:45",
  1151. ServicePortName: makeServicePortName("ns4", "ep4", "p45"),
  1152. }},
  1153. expectedStaleServiceNames: map[ServicePortName]bool{
  1154. makeServicePortName("ns1", "ep1", "p12"): true,
  1155. makeServicePortName("ns1", "ep1", "p122"): true,
  1156. makeServicePortName("ns3", "ep3", "p33"): true,
  1157. },
  1158. expectedHealthchecks: map[types.NamespacedName]int{
  1159. makeNSN("ns4", "ep4"): 1,
  1160. },
  1161. }, {
  1162. // Case[15]: change from 0 endpoint address to 1 unnamed port
  1163. previousEndpoints: []*v1.Endpoints{
  1164. makeTestEndpoints("ns1", "ep1", emptyEndpoint),
  1165. },
  1166. currentEndpoints: []*v1.Endpoints{
  1167. makeTestEndpoints("ns1", "ep1", unnamedPort),
  1168. },
  1169. oldEndpoints: map[ServicePortName][]*BaseEndpointInfo{},
  1170. expectedResult: map[ServicePortName][]*BaseEndpointInfo{
  1171. makeServicePortName("ns1", "ep1", ""): {
  1172. {Endpoint: "1.1.1.1:11", IsLocal: false},
  1173. },
  1174. },
  1175. expectedStaleEndpoints: []ServiceEndpoint{},
  1176. expectedStaleServiceNames: map[ServicePortName]bool{
  1177. makeServicePortName("ns1", "ep1", ""): true,
  1178. },
  1179. expectedHealthchecks: map[types.NamespacedName]int{},
  1180. },
  1181. }
  1182. for tci, tc := range testCases {
  1183. fp := newFakeProxier()
  1184. fp.hostname = nodeName
  1185. // First check that after adding all previous versions of endpoints,
  1186. // the fp.oldEndpoints is as we expect.
  1187. for i := range tc.previousEndpoints {
  1188. if tc.previousEndpoints[i] != nil {
  1189. fp.addEndpoints(tc.previousEndpoints[i])
  1190. }
  1191. }
  1192. fp.endpointsMap.Update(fp.endpointsChanges)
  1193. compareEndpointsMaps(t, tci, fp.endpointsMap, tc.oldEndpoints)
  1194. // Now let's call appropriate handlers to get to state we want to be.
  1195. if len(tc.previousEndpoints) != len(tc.currentEndpoints) {
  1196. t.Fatalf("[%d] different lengths of previous and current endpoints", tci)
  1197. continue
  1198. }
  1199. for i := range tc.previousEndpoints {
  1200. prev, curr := tc.previousEndpoints[i], tc.currentEndpoints[i]
  1201. switch {
  1202. case prev == nil:
  1203. fp.addEndpoints(curr)
  1204. case curr == nil:
  1205. fp.deleteEndpoints(prev)
  1206. default:
  1207. fp.updateEndpoints(prev, curr)
  1208. }
  1209. }
  1210. result := fp.endpointsMap.Update(fp.endpointsChanges)
  1211. newMap := fp.endpointsMap
  1212. compareEndpointsMaps(t, tci, newMap, tc.expectedResult)
  1213. if len(result.StaleEndpoints) != len(tc.expectedStaleEndpoints) {
  1214. t.Errorf("[%d] expected %d staleEndpoints, got %d: %v", tci, len(tc.expectedStaleEndpoints), len(result.StaleEndpoints), result.StaleEndpoints)
  1215. }
  1216. for _, x := range tc.expectedStaleEndpoints {
  1217. found := false
  1218. for _, stale := range result.StaleEndpoints {
  1219. if stale == x {
  1220. found = true
  1221. break
  1222. }
  1223. }
  1224. if !found {
  1225. t.Errorf("[%d] expected staleEndpoints[%v], but didn't find it: %v", tci, x, result.StaleEndpoints)
  1226. }
  1227. }
  1228. if len(result.StaleServiceNames) != len(tc.expectedStaleServiceNames) {
  1229. t.Errorf("[%d] expected %d staleServiceNames, got %d: %v", tci, len(tc.expectedStaleServiceNames), len(result.StaleServiceNames), result.StaleServiceNames)
  1230. }
  1231. for svcName := range tc.expectedStaleServiceNames {
  1232. found := false
  1233. for _, stale := range result.StaleServiceNames {
  1234. if stale == svcName {
  1235. found = true
  1236. }
  1237. }
  1238. if !found {
  1239. t.Errorf("[%d] expected staleServiceNames[%v], but didn't find it: %v", tci, svcName, result.StaleServiceNames)
  1240. }
  1241. }
  1242. if !reflect.DeepEqual(result.HCEndpointsLocalIPSize, tc.expectedHealthchecks) {
  1243. t.Errorf("[%d] expected healthchecks %v, got %v", tci, tc.expectedHealthchecks, result.HCEndpointsLocalIPSize)
  1244. }
  1245. }
  1246. }
  1247. func TestLastChangeTriggerTime(t *testing.T) {
  1248. t0 := time.Date(2018, 01, 01, 0, 0, 0, 0, time.UTC)
  1249. t1 := t0.Add(time.Second)
  1250. t2 := t1.Add(time.Second)
  1251. t3 := t2.Add(time.Second)
  1252. createEndpoints := func(namespace, name string, triggerTime time.Time) *v1.Endpoints {
  1253. e := makeTestEndpoints(namespace, name, func(ept *v1.Endpoints) {
  1254. ept.Subsets = []v1.EndpointSubset{{
  1255. Addresses: []v1.EndpointAddress{{IP: "1.1.1.1"}},
  1256. Ports: []v1.EndpointPort{{Port: 11}},
  1257. }}
  1258. })
  1259. e.Annotations[v1.EndpointsLastChangeTriggerTime] = triggerTime.Format(time.RFC3339Nano)
  1260. return e
  1261. }
  1262. modifyEndpoints := func(endpoints *v1.Endpoints, triggerTime time.Time) *v1.Endpoints {
  1263. e := endpoints.DeepCopy()
  1264. e.Subsets[0].Ports[0].Port++
  1265. e.Annotations[v1.EndpointsLastChangeTriggerTime] = triggerTime.Format(time.RFC3339Nano)
  1266. return e
  1267. }
  1268. sortTimeSlice := func(data []time.Time) {
  1269. sort.Slice(data, func(i, j int) bool { return data[i].Before(data[j]) })
  1270. }
  1271. testCases := []struct {
  1272. name string
  1273. scenario func(fp *FakeProxier)
  1274. expected []time.Time
  1275. }{
  1276. {
  1277. name: "Single addEndpoints",
  1278. scenario: func(fp *FakeProxier) {
  1279. e := createEndpoints("ns", "ep1", t0)
  1280. fp.addEndpoints(e)
  1281. },
  1282. expected: []time.Time{t0},
  1283. },
  1284. {
  1285. name: "addEndpoints then updatedEndpoints",
  1286. scenario: func(fp *FakeProxier) {
  1287. e := createEndpoints("ns", "ep1", t0)
  1288. fp.addEndpoints(e)
  1289. e1 := modifyEndpoints(e, t1)
  1290. fp.updateEndpoints(e, e1)
  1291. },
  1292. expected: []time.Time{t0, t1},
  1293. },
  1294. {
  1295. name: "Add two endpoints then modify one",
  1296. scenario: func(fp *FakeProxier) {
  1297. e1 := createEndpoints("ns", "ep1", t1)
  1298. fp.addEndpoints(e1)
  1299. e2 := createEndpoints("ns", "ep2", t2)
  1300. fp.addEndpoints(e2)
  1301. e11 := modifyEndpoints(e1, t3)
  1302. fp.updateEndpoints(e1, e11)
  1303. },
  1304. expected: []time.Time{t1, t2, t3},
  1305. },
  1306. {
  1307. name: "Endpoints without annotation set",
  1308. scenario: func(fp *FakeProxier) {
  1309. e := createEndpoints("ns", "ep1", t1)
  1310. delete(e.Annotations, v1.EndpointsLastChangeTriggerTime)
  1311. fp.addEndpoints(e)
  1312. },
  1313. expected: []time.Time{},
  1314. },
  1315. {
  1316. name: "addEndpoints then deleteEndpoints",
  1317. scenario: func(fp *FakeProxier) {
  1318. e := createEndpoints("ns", "ep1", t1)
  1319. fp.addEndpoints(e)
  1320. fp.deleteEndpoints(e)
  1321. },
  1322. expected: []time.Time{},
  1323. },
  1324. {
  1325. name: "add then delete then add again",
  1326. scenario: func(fp *FakeProxier) {
  1327. e := createEndpoints("ns", "ep1", t1)
  1328. fp.addEndpoints(e)
  1329. fp.deleteEndpoints(e)
  1330. e = modifyEndpoints(e, t2)
  1331. fp.addEndpoints(e)
  1332. },
  1333. expected: []time.Time{t2},
  1334. },
  1335. }
  1336. for _, tc := range testCases {
  1337. fp := newFakeProxier()
  1338. tc.scenario(fp)
  1339. result := fp.endpointsMap.Update(fp.endpointsChanges)
  1340. got := result.LastChangeTriggerTimes
  1341. sortTimeSlice(got)
  1342. sortTimeSlice(tc.expected)
  1343. if !reflect.DeepEqual(got, tc.expected) {
  1344. t.Errorf("%s: Invalid LastChangeTriggerTimes, expected: %v, got: %v",
  1345. tc.name, tc.expected, result.LastChangeTriggerTimes)
  1346. }
  1347. }
  1348. }
  1349. func compareEndpointsMaps(t *testing.T, tci int, newMap EndpointsMap, expected map[ServicePortName][]*BaseEndpointInfo) {
  1350. if len(newMap) != len(expected) {
  1351. t.Errorf("[%d] expected %d results, got %d: %v", tci, len(expected), len(newMap), newMap)
  1352. }
  1353. for x := range expected {
  1354. if len(newMap[x]) != len(expected[x]) {
  1355. t.Errorf("[%d] expected %d endpoints for %v, got %d", tci, len(expected[x]), x, len(newMap[x]))
  1356. } else {
  1357. for i := range expected[x] {
  1358. newEp, ok := newMap[x][i].(*BaseEndpointInfo)
  1359. if !ok {
  1360. t.Errorf("Failed to cast endpointsInfo")
  1361. continue
  1362. }
  1363. if *newEp != *(expected[x][i]) {
  1364. t.Errorf("[%d] expected new[%v][%d] to be %v, got %v", tci, x, i, expected[x][i], newEp)
  1365. }
  1366. }
  1367. }
  1368. }
  1369. }