range_allocator_test.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. /*
  2. Copyright 2016 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 ipam
  14. import (
  15. "net"
  16. "testing"
  17. "time"
  18. "k8s.io/api/core/v1"
  19. metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
  20. "k8s.io/apimachinery/pkg/util/wait"
  21. "k8s.io/client-go/informers"
  22. coreinformers "k8s.io/client-go/informers/core/v1"
  23. "k8s.io/client-go/kubernetes/fake"
  24. "k8s.io/kubernetes/pkg/controller"
  25. "k8s.io/kubernetes/pkg/controller/testutil"
  26. )
  27. const (
  28. nodePollInterval = 100 * time.Millisecond
  29. )
  30. var alwaysReady = func() bool { return true }
  31. func waitForUpdatedNodeWithTimeout(nodeHandler *testutil.FakeNodeHandler, number int, timeout time.Duration) error {
  32. return wait.Poll(nodePollInterval, timeout, func() (bool, error) {
  33. if len(nodeHandler.GetUpdatedNodesCopy()) >= number {
  34. return true, nil
  35. }
  36. return false, nil
  37. })
  38. }
  39. // Creates a fakeNodeInformer using the provided fakeNodeHandler.
  40. func getFakeNodeInformer(fakeNodeHandler *testutil.FakeNodeHandler) coreinformers.NodeInformer {
  41. fakeClient := &fake.Clientset{}
  42. fakeInformerFactory := informers.NewSharedInformerFactory(fakeClient, controller.NoResyncPeriodFunc())
  43. fakeNodeInformer := fakeInformerFactory.Core().V1().Nodes()
  44. for _, node := range fakeNodeHandler.Existing {
  45. fakeNodeInformer.Informer().GetStore().Add(node)
  46. }
  47. return fakeNodeInformer
  48. }
  49. func TestAllocateOrOccupyCIDRSuccess(t *testing.T) {
  50. testCases := []struct {
  51. description string
  52. fakeNodeHandler *testutil.FakeNodeHandler
  53. clusterCIDR *net.IPNet
  54. serviceCIDR *net.IPNet
  55. subNetMaskSize int
  56. expectedAllocatedCIDR string
  57. allocatedCIDRs []string
  58. }{
  59. {
  60. description: "When there's no ServiceCIDR return first CIDR in range",
  61. fakeNodeHandler: &testutil.FakeNodeHandler{
  62. Existing: []*v1.Node{
  63. {
  64. ObjectMeta: metav1.ObjectMeta{
  65. Name: "node0",
  66. },
  67. },
  68. },
  69. Clientset: fake.NewSimpleClientset(),
  70. },
  71. clusterCIDR: func() *net.IPNet {
  72. _, clusterCIDR, _ := net.ParseCIDR("127.123.234.0/24")
  73. return clusterCIDR
  74. }(),
  75. serviceCIDR: nil,
  76. subNetMaskSize: 30,
  77. expectedAllocatedCIDR: "127.123.234.0/30",
  78. },
  79. {
  80. description: "Correctly filter out ServiceCIDR",
  81. fakeNodeHandler: &testutil.FakeNodeHandler{
  82. Existing: []*v1.Node{
  83. {
  84. ObjectMeta: metav1.ObjectMeta{
  85. Name: "node0",
  86. },
  87. },
  88. },
  89. Clientset: fake.NewSimpleClientset(),
  90. },
  91. clusterCIDR: func() *net.IPNet {
  92. _, clusterCIDR, _ := net.ParseCIDR("127.123.234.0/24")
  93. return clusterCIDR
  94. }(),
  95. serviceCIDR: func() *net.IPNet {
  96. _, clusterCIDR, _ := net.ParseCIDR("127.123.234.0/26")
  97. return clusterCIDR
  98. }(),
  99. subNetMaskSize: 30,
  100. // it should return first /30 CIDR after service range
  101. expectedAllocatedCIDR: "127.123.234.64/30",
  102. },
  103. {
  104. description: "Correctly ignore already allocated CIDRs",
  105. fakeNodeHandler: &testutil.FakeNodeHandler{
  106. Existing: []*v1.Node{
  107. {
  108. ObjectMeta: metav1.ObjectMeta{
  109. Name: "node0",
  110. },
  111. },
  112. },
  113. Clientset: fake.NewSimpleClientset(),
  114. },
  115. clusterCIDR: func() *net.IPNet {
  116. _, clusterCIDR, _ := net.ParseCIDR("127.123.234.0/24")
  117. return clusterCIDR
  118. }(),
  119. serviceCIDR: func() *net.IPNet {
  120. _, clusterCIDR, _ := net.ParseCIDR("127.123.234.0/26")
  121. return clusterCIDR
  122. }(),
  123. subNetMaskSize: 30,
  124. allocatedCIDRs: []string{"127.123.234.64/30", "127.123.234.68/30", "127.123.234.72/30", "127.123.234.80/30"},
  125. expectedAllocatedCIDR: "127.123.234.76/30",
  126. },
  127. }
  128. testFunc := func(tc struct {
  129. description string
  130. fakeNodeHandler *testutil.FakeNodeHandler
  131. clusterCIDR *net.IPNet
  132. serviceCIDR *net.IPNet
  133. subNetMaskSize int
  134. expectedAllocatedCIDR string
  135. allocatedCIDRs []string
  136. }) {
  137. // Initialize the range allocator.
  138. allocator, _ := NewCIDRRangeAllocator(tc.fakeNodeHandler, getFakeNodeInformer(tc.fakeNodeHandler), tc.clusterCIDR, tc.serviceCIDR, tc.subNetMaskSize, nil)
  139. rangeAllocator, ok := allocator.(*rangeAllocator)
  140. if !ok {
  141. t.Logf("%v: found non-default implementation of CIDRAllocator, skipping white-box test...", tc.description)
  142. return
  143. }
  144. rangeAllocator.nodesSynced = alwaysReady
  145. rangeAllocator.recorder = testutil.NewFakeRecorder()
  146. go allocator.Run(wait.NeverStop)
  147. // this is a bit of white box testing
  148. for _, allocated := range tc.allocatedCIDRs {
  149. _, cidr, err := net.ParseCIDR(allocated)
  150. if err != nil {
  151. t.Fatalf("%v: unexpected error when parsing CIDR %v: %v", tc.description, allocated, err)
  152. }
  153. if err = rangeAllocator.cidrs.Occupy(cidr); err != nil {
  154. t.Fatalf("%v: unexpected error when occupying CIDR %v: %v", tc.description, allocated, err)
  155. }
  156. }
  157. if err := allocator.AllocateOrOccupyCIDR(tc.fakeNodeHandler.Existing[0]); err != nil {
  158. t.Errorf("%v: unexpected error in AllocateOrOccupyCIDR: %v", tc.description, err)
  159. }
  160. if err := waitForUpdatedNodeWithTimeout(tc.fakeNodeHandler, 1, wait.ForeverTestTimeout); err != nil {
  161. t.Fatalf("%v: timeout while waiting for Node update: %v", tc.description, err)
  162. }
  163. found := false
  164. seenCIDRs := []string{}
  165. for _, updatedNode := range tc.fakeNodeHandler.GetUpdatedNodesCopy() {
  166. seenCIDRs = append(seenCIDRs, updatedNode.Spec.PodCIDR)
  167. if updatedNode.Spec.PodCIDR == tc.expectedAllocatedCIDR {
  168. found = true
  169. break
  170. }
  171. }
  172. if !found {
  173. t.Errorf("%v: Unable to find allocated CIDR %v, found updated Nodes with CIDRs: %v",
  174. tc.description, tc.expectedAllocatedCIDR, seenCIDRs)
  175. }
  176. }
  177. for _, tc := range testCases {
  178. testFunc(tc)
  179. }
  180. }
  181. func TestAllocateOrOccupyCIDRFailure(t *testing.T) {
  182. testCases := []struct {
  183. description string
  184. fakeNodeHandler *testutil.FakeNodeHandler
  185. clusterCIDR *net.IPNet
  186. serviceCIDR *net.IPNet
  187. subNetMaskSize int
  188. allocatedCIDRs []string
  189. }{
  190. {
  191. description: "When there's no ServiceCIDR return first CIDR in range",
  192. fakeNodeHandler: &testutil.FakeNodeHandler{
  193. Existing: []*v1.Node{
  194. {
  195. ObjectMeta: metav1.ObjectMeta{
  196. Name: "node0",
  197. },
  198. },
  199. },
  200. Clientset: fake.NewSimpleClientset(),
  201. },
  202. clusterCIDR: func() *net.IPNet {
  203. _, clusterCIDR, _ := net.ParseCIDR("127.123.234.0/28")
  204. return clusterCIDR
  205. }(),
  206. serviceCIDR: nil,
  207. subNetMaskSize: 30,
  208. allocatedCIDRs: []string{"127.123.234.0/30", "127.123.234.4/30", "127.123.234.8/30", "127.123.234.12/30"},
  209. },
  210. }
  211. testFunc := func(tc struct {
  212. description string
  213. fakeNodeHandler *testutil.FakeNodeHandler
  214. clusterCIDR *net.IPNet
  215. serviceCIDR *net.IPNet
  216. subNetMaskSize int
  217. allocatedCIDRs []string
  218. }) {
  219. // Initialize the range allocator.
  220. allocator, _ := NewCIDRRangeAllocator(tc.fakeNodeHandler, getFakeNodeInformer(tc.fakeNodeHandler), tc.clusterCIDR, tc.serviceCIDR, tc.subNetMaskSize, nil)
  221. rangeAllocator, ok := allocator.(*rangeAllocator)
  222. if !ok {
  223. t.Logf("%v: found non-default implementation of CIDRAllocator, skipping white-box test...", tc.description)
  224. return
  225. }
  226. rangeAllocator.nodesSynced = alwaysReady
  227. rangeAllocator.recorder = testutil.NewFakeRecorder()
  228. go allocator.Run(wait.NeverStop)
  229. // this is a bit of white box testing
  230. for _, allocated := range tc.allocatedCIDRs {
  231. _, cidr, err := net.ParseCIDR(allocated)
  232. if err != nil {
  233. t.Fatalf("%v: unexpected error when parsing CIDR %v: %v", tc.description, allocated, err)
  234. }
  235. err = rangeAllocator.cidrs.Occupy(cidr)
  236. if err != nil {
  237. t.Fatalf("%v: unexpected error when occupying CIDR %v: %v", tc.description, allocated, err)
  238. }
  239. }
  240. if err := allocator.AllocateOrOccupyCIDR(tc.fakeNodeHandler.Existing[0]); err == nil {
  241. t.Errorf("%v: unexpected success in AllocateOrOccupyCIDR: %v", tc.description, err)
  242. }
  243. // We don't expect any updates, so just sleep for some time
  244. time.Sleep(time.Second)
  245. if len(tc.fakeNodeHandler.GetUpdatedNodesCopy()) != 0 {
  246. t.Fatalf("%v: unexpected update of nodes: %v", tc.description, tc.fakeNodeHandler.GetUpdatedNodesCopy())
  247. }
  248. seenCIDRs := []string{}
  249. for _, updatedNode := range tc.fakeNodeHandler.GetUpdatedNodesCopy() {
  250. if updatedNode.Spec.PodCIDR != "" {
  251. seenCIDRs = append(seenCIDRs, updatedNode.Spec.PodCIDR)
  252. }
  253. }
  254. if len(seenCIDRs) != 0 {
  255. t.Errorf("%v: Seen assigned CIDRs when not expected: %v",
  256. tc.description, seenCIDRs)
  257. }
  258. }
  259. for _, tc := range testCases {
  260. testFunc(tc)
  261. }
  262. }
  263. func TestReleaseCIDRSuccess(t *testing.T) {
  264. testCases := []struct {
  265. description string
  266. fakeNodeHandler *testutil.FakeNodeHandler
  267. clusterCIDR *net.IPNet
  268. serviceCIDR *net.IPNet
  269. subNetMaskSize int
  270. expectedAllocatedCIDRFirstRound string
  271. expectedAllocatedCIDRSecondRound string
  272. allocatedCIDRs []string
  273. cidrsToRelease []string
  274. }{
  275. {
  276. description: "Correctly release preallocated CIDR",
  277. fakeNodeHandler: &testutil.FakeNodeHandler{
  278. Existing: []*v1.Node{
  279. {
  280. ObjectMeta: metav1.ObjectMeta{
  281. Name: "node0",
  282. },
  283. },
  284. },
  285. Clientset: fake.NewSimpleClientset(),
  286. },
  287. clusterCIDR: func() *net.IPNet {
  288. _, clusterCIDR, _ := net.ParseCIDR("127.123.234.0/28")
  289. return clusterCIDR
  290. }(),
  291. serviceCIDR: nil,
  292. subNetMaskSize: 30,
  293. allocatedCIDRs: []string{"127.123.234.0/30", "127.123.234.4/30", "127.123.234.8/30", "127.123.234.12/30"},
  294. expectedAllocatedCIDRFirstRound: "",
  295. cidrsToRelease: []string{"127.123.234.4/30"},
  296. expectedAllocatedCIDRSecondRound: "127.123.234.4/30",
  297. },
  298. {
  299. description: "Correctly recycle CIDR",
  300. fakeNodeHandler: &testutil.FakeNodeHandler{
  301. Existing: []*v1.Node{
  302. {
  303. ObjectMeta: metav1.ObjectMeta{
  304. Name: "node0",
  305. },
  306. },
  307. },
  308. Clientset: fake.NewSimpleClientset(),
  309. },
  310. clusterCIDR: func() *net.IPNet {
  311. _, clusterCIDR, _ := net.ParseCIDR("127.123.234.0/28")
  312. return clusterCIDR
  313. }(),
  314. serviceCIDR: nil,
  315. subNetMaskSize: 30,
  316. allocatedCIDRs: []string{"127.123.234.4/30", "127.123.234.8/30", "127.123.234.12/30"},
  317. expectedAllocatedCIDRFirstRound: "127.123.234.0/30",
  318. cidrsToRelease: []string{"127.123.234.0/30"},
  319. expectedAllocatedCIDRSecondRound: "127.123.234.0/30",
  320. },
  321. }
  322. testFunc := func(tc struct {
  323. description string
  324. fakeNodeHandler *testutil.FakeNodeHandler
  325. clusterCIDR *net.IPNet
  326. serviceCIDR *net.IPNet
  327. subNetMaskSize int
  328. expectedAllocatedCIDRFirstRound string
  329. expectedAllocatedCIDRSecondRound string
  330. allocatedCIDRs []string
  331. cidrsToRelease []string
  332. }) {
  333. // Initialize the range allocator.
  334. allocator, _ := NewCIDRRangeAllocator(tc.fakeNodeHandler, getFakeNodeInformer(tc.fakeNodeHandler), tc.clusterCIDR, tc.serviceCIDR, tc.subNetMaskSize, nil)
  335. rangeAllocator, ok := allocator.(*rangeAllocator)
  336. if !ok {
  337. t.Logf("%v: found non-default implementation of CIDRAllocator, skipping white-box test...", tc.description)
  338. return
  339. }
  340. rangeAllocator.nodesSynced = alwaysReady
  341. rangeAllocator.recorder = testutil.NewFakeRecorder()
  342. go allocator.Run(wait.NeverStop)
  343. // this is a bit of white box testing
  344. for _, allocated := range tc.allocatedCIDRs {
  345. _, cidr, err := net.ParseCIDR(allocated)
  346. if err != nil {
  347. t.Fatalf("%v: unexpected error when parsing CIDR %v: %v", tc.description, allocated, err)
  348. }
  349. err = rangeAllocator.cidrs.Occupy(cidr)
  350. if err != nil {
  351. t.Fatalf("%v: unexpected error when occupying CIDR %v: %v", tc.description, allocated, err)
  352. }
  353. }
  354. err := allocator.AllocateOrOccupyCIDR(tc.fakeNodeHandler.Existing[0])
  355. if tc.expectedAllocatedCIDRFirstRound != "" {
  356. if err != nil {
  357. t.Fatalf("%v: unexpected error in AllocateOrOccupyCIDR: %v", tc.description, err)
  358. }
  359. if err := waitForUpdatedNodeWithTimeout(tc.fakeNodeHandler, 1, wait.ForeverTestTimeout); err != nil {
  360. t.Fatalf("%v: timeout while waiting for Node update: %v", tc.description, err)
  361. }
  362. } else {
  363. if err == nil {
  364. t.Fatalf("%v: unexpected success in AllocateOrOccupyCIDR: %v", tc.description, err)
  365. }
  366. // We don't expect any updates here
  367. time.Sleep(time.Second)
  368. if len(tc.fakeNodeHandler.GetUpdatedNodesCopy()) != 0 {
  369. t.Fatalf("%v: unexpected update of nodes: %v", tc.description, tc.fakeNodeHandler.GetUpdatedNodesCopy())
  370. }
  371. }
  372. for _, cidrToRelease := range tc.cidrsToRelease {
  373. nodeToRelease := v1.Node{
  374. ObjectMeta: metav1.ObjectMeta{
  375. Name: "node0",
  376. },
  377. }
  378. nodeToRelease.Spec.PodCIDR = cidrToRelease
  379. err = allocator.ReleaseCIDR(&nodeToRelease)
  380. if err != nil {
  381. t.Fatalf("%v: unexpected error in ReleaseCIDR: %v", tc.description, err)
  382. }
  383. }
  384. if err = allocator.AllocateOrOccupyCIDR(tc.fakeNodeHandler.Existing[0]); err != nil {
  385. t.Fatalf("%v: unexpected error in AllocateOrOccupyCIDR: %v", tc.description, err)
  386. }
  387. if err := waitForUpdatedNodeWithTimeout(tc.fakeNodeHandler, 1, wait.ForeverTestTimeout); err != nil {
  388. t.Fatalf("%v: timeout while waiting for Node update: %v", tc.description, err)
  389. }
  390. found := false
  391. seenCIDRs := []string{}
  392. for _, updatedNode := range tc.fakeNodeHandler.GetUpdatedNodesCopy() {
  393. seenCIDRs = append(seenCIDRs, updatedNode.Spec.PodCIDR)
  394. if updatedNode.Spec.PodCIDR == tc.expectedAllocatedCIDRSecondRound {
  395. found = true
  396. break
  397. }
  398. }
  399. if !found {
  400. t.Errorf("%v: Unable to find allocated CIDR %v, found updated Nodes with CIDRs: %v",
  401. tc.description, tc.expectedAllocatedCIDRSecondRound, seenCIDRs)
  402. }
  403. }
  404. for _, tc := range testCases {
  405. testFunc(tc)
  406. }
  407. }