lease_test.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651
  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 reconcilers
  14. /*
  15. Original Source:
  16. https://github.com/openshift/origin/blob/bb340c5dd5ff72718be86fb194dedc0faed7f4c7/pkg/cmd/server/election/lease_endpoint_reconciler_test.go
  17. */
  18. import (
  19. "net"
  20. "reflect"
  21. "testing"
  22. corev1 "k8s.io/api/core/v1"
  23. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  24. "k8s.io/client-go/kubernetes/fake"
  25. )
  26. type fakeLeases struct {
  27. keys map[string]bool
  28. }
  29. var _ Leases = &fakeLeases{}
  30. func newFakeLeases() *fakeLeases {
  31. return &fakeLeases{make(map[string]bool)}
  32. }
  33. func (f *fakeLeases) ListLeases() ([]string, error) {
  34. res := make([]string, 0, len(f.keys))
  35. for ip := range f.keys {
  36. res = append(res, ip)
  37. }
  38. return res, nil
  39. }
  40. func (f *fakeLeases) UpdateLease(ip string) error {
  41. f.keys[ip] = true
  42. return nil
  43. }
  44. func (f *fakeLeases) RemoveLease(ip string) error {
  45. delete(f.keys, ip)
  46. return nil
  47. }
  48. func (f *fakeLeases) SetKeys(keys []string) {
  49. for _, ip := range keys {
  50. f.keys[ip] = false
  51. }
  52. }
  53. func (f *fakeLeases) GetUpdatedKeys() []string {
  54. res := []string{}
  55. for ip, updated := range f.keys {
  56. if updated {
  57. res = append(res, ip)
  58. }
  59. }
  60. return res
  61. }
  62. func TestLeaseEndpointReconciler(t *testing.T) {
  63. ns := corev1.NamespaceDefault
  64. om := func(name string) metav1.ObjectMeta {
  65. return metav1.ObjectMeta{Namespace: ns, Name: name}
  66. }
  67. reconcileTests := []struct {
  68. testName string
  69. serviceName string
  70. ip string
  71. endpointPorts []corev1.EndpointPort
  72. endpointKeys []string
  73. endpoints *corev1.EndpointsList
  74. expectUpdate *corev1.Endpoints // nil means none expected
  75. }{
  76. {
  77. testName: "no existing endpoints",
  78. serviceName: "foo",
  79. ip: "1.2.3.4",
  80. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  81. endpoints: nil,
  82. expectUpdate: &corev1.Endpoints{
  83. ObjectMeta: om("foo"),
  84. Subsets: []corev1.EndpointSubset{{
  85. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  86. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  87. }},
  88. },
  89. },
  90. {
  91. testName: "existing endpoints satisfy",
  92. serviceName: "foo",
  93. ip: "1.2.3.4",
  94. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  95. endpoints: &corev1.EndpointsList{
  96. Items: []corev1.Endpoints{{
  97. ObjectMeta: om("foo"),
  98. Subsets: []corev1.EndpointSubset{{
  99. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  100. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  101. }},
  102. }},
  103. },
  104. },
  105. {
  106. testName: "existing endpoints satisfy + refresh existing key",
  107. serviceName: "foo",
  108. ip: "1.2.3.4",
  109. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  110. endpointKeys: []string{"1.2.3.4"},
  111. endpoints: &corev1.EndpointsList{
  112. Items: []corev1.Endpoints{{
  113. ObjectMeta: om("foo"),
  114. Subsets: []corev1.EndpointSubset{{
  115. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  116. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  117. }},
  118. }},
  119. },
  120. },
  121. {
  122. testName: "existing endpoints satisfy but too many",
  123. serviceName: "foo",
  124. ip: "1.2.3.4",
  125. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  126. endpoints: &corev1.EndpointsList{
  127. Items: []corev1.Endpoints{{
  128. ObjectMeta: om("foo"),
  129. Subsets: []corev1.EndpointSubset{{
  130. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}, {IP: "4.3.2.1"}},
  131. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  132. }},
  133. }},
  134. },
  135. expectUpdate: &corev1.Endpoints{
  136. ObjectMeta: om("foo"),
  137. Subsets: []corev1.EndpointSubset{{
  138. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  139. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  140. }},
  141. },
  142. },
  143. {
  144. testName: "existing endpoints satisfy but too many + extra masters",
  145. serviceName: "foo",
  146. ip: "1.2.3.4",
  147. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  148. endpointKeys: []string{"1.2.3.4", "4.3.2.2", "4.3.2.3", "4.3.2.4"},
  149. endpoints: &corev1.EndpointsList{
  150. Items: []corev1.Endpoints{{
  151. ObjectMeta: om("foo"),
  152. Subsets: []corev1.EndpointSubset{{
  153. Addresses: []corev1.EndpointAddress{
  154. {IP: "1.2.3.4"},
  155. {IP: "4.3.2.1"},
  156. {IP: "4.3.2.2"},
  157. {IP: "4.3.2.3"},
  158. {IP: "4.3.2.4"},
  159. },
  160. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  161. }},
  162. }},
  163. },
  164. expectUpdate: &corev1.Endpoints{
  165. ObjectMeta: om("foo"),
  166. Subsets: []corev1.EndpointSubset{{
  167. Addresses: []corev1.EndpointAddress{
  168. {IP: "1.2.3.4"},
  169. {IP: "4.3.2.2"},
  170. {IP: "4.3.2.3"},
  171. {IP: "4.3.2.4"},
  172. },
  173. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  174. }},
  175. },
  176. },
  177. {
  178. testName: "existing endpoints satisfy but too many + extra masters + delete first",
  179. serviceName: "foo",
  180. ip: "4.3.2.4",
  181. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  182. endpointKeys: []string{"4.3.2.1", "4.3.2.2", "4.3.2.3", "4.3.2.4"},
  183. endpoints: &corev1.EndpointsList{
  184. Items: []corev1.Endpoints{{
  185. ObjectMeta: om("foo"),
  186. Subsets: []corev1.EndpointSubset{{
  187. Addresses: []corev1.EndpointAddress{
  188. {IP: "1.2.3.4"},
  189. {IP: "4.3.2.1"},
  190. {IP: "4.3.2.2"},
  191. {IP: "4.3.2.3"},
  192. {IP: "4.3.2.4"},
  193. },
  194. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  195. }},
  196. }},
  197. },
  198. expectUpdate: &corev1.Endpoints{
  199. ObjectMeta: om("foo"),
  200. Subsets: []corev1.EndpointSubset{{
  201. Addresses: []corev1.EndpointAddress{
  202. {IP: "4.3.2.1"},
  203. {IP: "4.3.2.2"},
  204. {IP: "4.3.2.3"},
  205. {IP: "4.3.2.4"},
  206. },
  207. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  208. }},
  209. },
  210. },
  211. {
  212. testName: "existing endpoints current IP missing",
  213. serviceName: "foo",
  214. ip: "4.3.2.2",
  215. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  216. endpointKeys: []string{"4.3.2.1"},
  217. endpoints: &corev1.EndpointsList{
  218. Items: []corev1.Endpoints{{
  219. ObjectMeta: om("foo"),
  220. Subsets: []corev1.EndpointSubset{{
  221. Addresses: []corev1.EndpointAddress{
  222. {IP: "4.3.2.1"},
  223. },
  224. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  225. }},
  226. }},
  227. },
  228. expectUpdate: &corev1.Endpoints{
  229. ObjectMeta: om("foo"),
  230. Subsets: []corev1.EndpointSubset{{
  231. Addresses: []corev1.EndpointAddress{
  232. {IP: "4.3.2.1"},
  233. {IP: "4.3.2.2"},
  234. },
  235. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  236. }},
  237. },
  238. },
  239. {
  240. testName: "existing endpoints wrong name",
  241. serviceName: "foo",
  242. ip: "1.2.3.4",
  243. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  244. endpoints: &corev1.EndpointsList{
  245. Items: []corev1.Endpoints{{
  246. ObjectMeta: om("bar"),
  247. Subsets: []corev1.EndpointSubset{{
  248. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  249. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  250. }},
  251. }},
  252. },
  253. expectUpdate: &corev1.Endpoints{
  254. ObjectMeta: om("foo"),
  255. Subsets: []corev1.EndpointSubset{{
  256. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  257. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  258. }},
  259. },
  260. },
  261. {
  262. testName: "existing endpoints wrong IP",
  263. serviceName: "foo",
  264. ip: "1.2.3.4",
  265. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  266. endpoints: &corev1.EndpointsList{
  267. Items: []corev1.Endpoints{{
  268. ObjectMeta: om("foo"),
  269. Subsets: []corev1.EndpointSubset{{
  270. Addresses: []corev1.EndpointAddress{{IP: "4.3.2.1"}},
  271. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  272. }},
  273. }},
  274. },
  275. expectUpdate: &corev1.Endpoints{
  276. ObjectMeta: om("foo"),
  277. Subsets: []corev1.EndpointSubset{{
  278. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  279. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  280. }},
  281. },
  282. },
  283. {
  284. testName: "existing endpoints wrong port",
  285. serviceName: "foo",
  286. ip: "1.2.3.4",
  287. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  288. endpoints: &corev1.EndpointsList{
  289. Items: []corev1.Endpoints{{
  290. ObjectMeta: om("foo"),
  291. Subsets: []corev1.EndpointSubset{{
  292. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  293. Ports: []corev1.EndpointPort{{Name: "foo", Port: 9090, Protocol: "TCP"}},
  294. }},
  295. }},
  296. },
  297. expectUpdate: &corev1.Endpoints{
  298. ObjectMeta: om("foo"),
  299. Subsets: []corev1.EndpointSubset{{
  300. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  301. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  302. }},
  303. },
  304. },
  305. {
  306. testName: "existing endpoints wrong protocol",
  307. serviceName: "foo",
  308. ip: "1.2.3.4",
  309. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  310. endpoints: &corev1.EndpointsList{
  311. Items: []corev1.Endpoints{{
  312. ObjectMeta: om("foo"),
  313. Subsets: []corev1.EndpointSubset{{
  314. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  315. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "UDP"}},
  316. }},
  317. }},
  318. },
  319. expectUpdate: &corev1.Endpoints{
  320. ObjectMeta: om("foo"),
  321. Subsets: []corev1.EndpointSubset{{
  322. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  323. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  324. }},
  325. },
  326. },
  327. {
  328. testName: "existing endpoints wrong port name",
  329. serviceName: "foo",
  330. ip: "1.2.3.4",
  331. endpointPorts: []corev1.EndpointPort{{Name: "baz", Port: 8080, Protocol: "TCP"}},
  332. endpoints: &corev1.EndpointsList{
  333. Items: []corev1.Endpoints{{
  334. ObjectMeta: om("foo"),
  335. Subsets: []corev1.EndpointSubset{{
  336. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  337. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  338. }},
  339. }},
  340. },
  341. expectUpdate: &corev1.Endpoints{
  342. ObjectMeta: om("foo"),
  343. Subsets: []corev1.EndpointSubset{{
  344. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  345. Ports: []corev1.EndpointPort{{Name: "baz", Port: 8080, Protocol: "TCP"}},
  346. }},
  347. },
  348. },
  349. {
  350. testName: "existing endpoints extra service ports satisfy",
  351. serviceName: "foo",
  352. ip: "1.2.3.4",
  353. endpointPorts: []corev1.EndpointPort{
  354. {Name: "foo", Port: 8080, Protocol: "TCP"},
  355. {Name: "bar", Port: 1000, Protocol: "TCP"},
  356. {Name: "baz", Port: 1010, Protocol: "TCP"},
  357. },
  358. endpoints: &corev1.EndpointsList{
  359. Items: []corev1.Endpoints{{
  360. ObjectMeta: om("foo"),
  361. Subsets: []corev1.EndpointSubset{{
  362. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  363. Ports: []corev1.EndpointPort{
  364. {Name: "foo", Port: 8080, Protocol: "TCP"},
  365. {Name: "bar", Port: 1000, Protocol: "TCP"},
  366. {Name: "baz", Port: 1010, Protocol: "TCP"},
  367. },
  368. }},
  369. }},
  370. },
  371. },
  372. {
  373. testName: "existing endpoints extra service ports missing port",
  374. serviceName: "foo",
  375. ip: "1.2.3.4",
  376. endpointPorts: []corev1.EndpointPort{
  377. {Name: "foo", Port: 8080, Protocol: "TCP"},
  378. {Name: "bar", Port: 1000, Protocol: "TCP"},
  379. },
  380. endpoints: &corev1.EndpointsList{
  381. Items: []corev1.Endpoints{{
  382. ObjectMeta: om("foo"),
  383. Subsets: []corev1.EndpointSubset{{
  384. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  385. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  386. }},
  387. }},
  388. },
  389. expectUpdate: &corev1.Endpoints{
  390. ObjectMeta: om("foo"),
  391. Subsets: []corev1.EndpointSubset{{
  392. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  393. Ports: []corev1.EndpointPort{
  394. {Name: "foo", Port: 8080, Protocol: "TCP"},
  395. {Name: "bar", Port: 1000, Protocol: "TCP"},
  396. },
  397. }},
  398. },
  399. },
  400. }
  401. for _, test := range reconcileTests {
  402. fakeLeases := newFakeLeases()
  403. fakeLeases.SetKeys(test.endpointKeys)
  404. clientset := fake.NewSimpleClientset()
  405. if test.endpoints != nil {
  406. for _, ep := range test.endpoints.Items {
  407. if _, err := clientset.CoreV1().Endpoints(ep.Namespace).Create(&ep); err != nil {
  408. t.Errorf("case %q: unexpected error: %v", test.testName, err)
  409. continue
  410. }
  411. }
  412. }
  413. r := NewLeaseEndpointReconciler(clientset.CoreV1(), fakeLeases)
  414. err := r.ReconcileEndpoints(test.serviceName, net.ParseIP(test.ip), test.endpointPorts, true)
  415. if err != nil {
  416. t.Errorf("case %q: unexpected error: %v", test.testName, err)
  417. }
  418. actualEndpoints, err := clientset.CoreV1().Endpoints(corev1.NamespaceDefault).Get(test.serviceName, metav1.GetOptions{})
  419. if err != nil {
  420. t.Errorf("case %q: unexpected error: %v", test.testName, err)
  421. }
  422. if test.expectUpdate != nil {
  423. if e, a := test.expectUpdate, actualEndpoints; !reflect.DeepEqual(e, a) {
  424. t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a)
  425. }
  426. }
  427. if updatedKeys := fakeLeases.GetUpdatedKeys(); len(updatedKeys) != 1 || updatedKeys[0] != test.ip {
  428. t.Errorf("case %q: expected the master's IP to be refreshed, but the following IPs were refreshed instead: %v", test.testName, updatedKeys)
  429. }
  430. }
  431. nonReconcileTests := []struct {
  432. testName string
  433. serviceName string
  434. ip string
  435. endpointPorts []corev1.EndpointPort
  436. endpointKeys []string
  437. endpoints *corev1.EndpointsList
  438. expectUpdate *corev1.Endpoints // nil means none expected
  439. }{
  440. {
  441. testName: "existing endpoints extra service ports missing port no update",
  442. serviceName: "foo",
  443. ip: "1.2.3.4",
  444. endpointPorts: []corev1.EndpointPort{
  445. {Name: "foo", Port: 8080, Protocol: "TCP"},
  446. {Name: "bar", Port: 1000, Protocol: "TCP"},
  447. },
  448. endpoints: &corev1.EndpointsList{
  449. Items: []corev1.Endpoints{{
  450. ObjectMeta: om("foo"),
  451. Subsets: []corev1.EndpointSubset{{
  452. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  453. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  454. }},
  455. }},
  456. },
  457. expectUpdate: nil,
  458. },
  459. {
  460. testName: "existing endpoints extra service ports, wrong ports, wrong IP",
  461. serviceName: "foo",
  462. ip: "1.2.3.4",
  463. endpointPorts: []corev1.EndpointPort{
  464. {Name: "foo", Port: 8080, Protocol: "TCP"},
  465. {Name: "bar", Port: 1000, Protocol: "TCP"},
  466. },
  467. endpoints: &corev1.EndpointsList{
  468. Items: []corev1.Endpoints{{
  469. ObjectMeta: om("foo"),
  470. Subsets: []corev1.EndpointSubset{{
  471. Addresses: []corev1.EndpointAddress{{IP: "4.3.2.1"}},
  472. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  473. }},
  474. }},
  475. },
  476. expectUpdate: &corev1.Endpoints{
  477. ObjectMeta: om("foo"),
  478. Subsets: []corev1.EndpointSubset{{
  479. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  480. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  481. }},
  482. },
  483. },
  484. {
  485. testName: "no existing endpoints",
  486. serviceName: "foo",
  487. ip: "1.2.3.4",
  488. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  489. endpoints: nil,
  490. expectUpdate: &corev1.Endpoints{
  491. ObjectMeta: om("foo"),
  492. Subsets: []corev1.EndpointSubset{{
  493. Addresses: []corev1.EndpointAddress{{IP: "1.2.3.4"}},
  494. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  495. }},
  496. },
  497. },
  498. }
  499. for _, test := range nonReconcileTests {
  500. t.Run(test.testName, func(t *testing.T) {
  501. fakeLeases := newFakeLeases()
  502. fakeLeases.SetKeys(test.endpointKeys)
  503. clientset := fake.NewSimpleClientset()
  504. if test.endpoints != nil {
  505. for _, ep := range test.endpoints.Items {
  506. if _, err := clientset.CoreV1().Endpoints(ep.Namespace).Create(&ep); err != nil {
  507. t.Errorf("case %q: unexpected error: %v", test.testName, err)
  508. continue
  509. }
  510. }
  511. }
  512. r := NewLeaseEndpointReconciler(clientset.CoreV1(), fakeLeases)
  513. err := r.ReconcileEndpoints(test.serviceName, net.ParseIP(test.ip), test.endpointPorts, false)
  514. if err != nil {
  515. t.Errorf("case %q: unexpected error: %v", test.testName, err)
  516. }
  517. actualEndpoints, err := clientset.CoreV1().Endpoints(corev1.NamespaceDefault).Get(test.serviceName, metav1.GetOptions{})
  518. if err != nil {
  519. t.Errorf("case %q: unexpected error: %v", test.testName, err)
  520. }
  521. if test.expectUpdate != nil {
  522. if e, a := test.expectUpdate, actualEndpoints; !reflect.DeepEqual(e, a) {
  523. t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a)
  524. }
  525. }
  526. if updatedKeys := fakeLeases.GetUpdatedKeys(); len(updatedKeys) != 1 || updatedKeys[0] != test.ip {
  527. t.Errorf("case %q: expected the master's IP to be refreshed, but the following IPs were refreshed instead: %v", test.testName, updatedKeys)
  528. }
  529. })
  530. }
  531. }
  532. func TestLeaseRemoveEndpoints(t *testing.T) {
  533. ns := corev1.NamespaceDefault
  534. om := func(name string) metav1.ObjectMeta {
  535. return metav1.ObjectMeta{Namespace: ns, Name: name}
  536. }
  537. stopTests := []struct {
  538. testName string
  539. serviceName string
  540. ip string
  541. endpointPorts []corev1.EndpointPort
  542. endpointKeys []string
  543. endpoints *corev1.EndpointsList
  544. expectUpdate *corev1.Endpoints // nil means none expected
  545. }{
  546. {
  547. testName: "successful stop reconciling",
  548. serviceName: "foo",
  549. ip: "1.2.3.4",
  550. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  551. endpointKeys: []string{"1.2.3.4", "4.3.2.2", "4.3.2.3", "4.3.2.4"},
  552. endpoints: &corev1.EndpointsList{
  553. Items: []corev1.Endpoints{{
  554. ObjectMeta: om("foo"),
  555. Subsets: []corev1.EndpointSubset{{
  556. Addresses: []corev1.EndpointAddress{
  557. {IP: "1.2.3.4"},
  558. {IP: "4.3.2.2"},
  559. {IP: "4.3.2.3"},
  560. {IP: "4.3.2.4"},
  561. },
  562. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  563. }},
  564. }},
  565. },
  566. expectUpdate: &corev1.Endpoints{
  567. ObjectMeta: om("foo"),
  568. Subsets: []corev1.EndpointSubset{{
  569. Addresses: []corev1.EndpointAddress{
  570. {IP: "4.3.2.2"},
  571. {IP: "4.3.2.3"},
  572. {IP: "4.3.2.4"},
  573. },
  574. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  575. }},
  576. },
  577. },
  578. {
  579. testName: "stop reconciling with ip not in endpoint ip list",
  580. serviceName: "foo",
  581. ip: "5.6.7.8",
  582. endpointPorts: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  583. endpointKeys: []string{"1.2.3.4", "4.3.2.2", "4.3.2.3", "4.3.2.4"},
  584. endpoints: &corev1.EndpointsList{
  585. Items: []corev1.Endpoints{{
  586. ObjectMeta: om("foo"),
  587. Subsets: []corev1.EndpointSubset{{
  588. Addresses: []corev1.EndpointAddress{
  589. {IP: "1.2.3.4"},
  590. {IP: "4.3.2.2"},
  591. {IP: "4.3.2.3"},
  592. {IP: "4.3.2.4"},
  593. },
  594. Ports: []corev1.EndpointPort{{Name: "foo", Port: 8080, Protocol: "TCP"}},
  595. }},
  596. }},
  597. },
  598. },
  599. }
  600. for _, test := range stopTests {
  601. t.Run(test.testName, func(t *testing.T) {
  602. fakeLeases := newFakeLeases()
  603. fakeLeases.SetKeys(test.endpointKeys)
  604. clientset := fake.NewSimpleClientset()
  605. for _, ep := range test.endpoints.Items {
  606. if _, err := clientset.CoreV1().Endpoints(ep.Namespace).Create(&ep); err != nil {
  607. t.Errorf("case %q: unexpected error: %v", test.testName, err)
  608. continue
  609. }
  610. }
  611. r := NewLeaseEndpointReconciler(clientset.CoreV1(), fakeLeases)
  612. err := r.RemoveEndpoints(test.serviceName, net.ParseIP(test.ip), test.endpointPorts)
  613. if err != nil {
  614. t.Errorf("case %q: unexpected error: %v", test.testName, err)
  615. }
  616. actualEndpoints, err := clientset.CoreV1().Endpoints(corev1.NamespaceDefault).Get(test.serviceName, metav1.GetOptions{})
  617. if err != nil {
  618. t.Errorf("case %q: unexpected error: %v", test.testName, err)
  619. }
  620. if test.expectUpdate != nil {
  621. if e, a := test.expectUpdate, actualEndpoints; !reflect.DeepEqual(e, a) {
  622. t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a)
  623. }
  624. }
  625. for _, key := range fakeLeases.GetUpdatedKeys() {
  626. if key == test.ip {
  627. t.Errorf("case %q: Found ip %s in leases but shouldn't be there", test.testName, key)
  628. }
  629. }
  630. })
  631. }
  632. }