common_test.go 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536
  1. package controller
  2. import (
  3. "context"
  4. "testing"
  5. "time"
  6. "github.com/gravitl/netmaker/models"
  7. "github.com/gravitl/netmaker/mongoconn"
  8. "github.com/stretchr/testify/assert"
  9. "go.mongodb.org/mongo-driver/bson"
  10. )
  11. type NodeValidationTC struct {
  12. testname string
  13. node models.Node
  14. errorMessage string
  15. }
  16. type NodeValidationUpdateTC struct {
  17. testname string
  18. node models.NodeUpdate
  19. errorMessage string
  20. }
  21. func createTestNode() models.Node {
  22. createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"}
  23. node, err := CreateNode(createnode, "skynet")
  24. if err != nil {
  25. panic(err)
  26. }
  27. return node
  28. }
  29. func TestCreateNode(t *testing.T) {
  30. deleteNet(t)
  31. createnode := models.Node{PublicKey: "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.0.0.1", MacAddress: "01:02:03:04:05:06", Password: "password", Network: "skynet"}
  32. createNet()
  33. err := ValidateNodeCreate("skynet", createnode)
  34. assert.Nil(t, err)
  35. node, err := CreateNode(createnode, "skynet")
  36. assert.Nil(t, err)
  37. assert.Equal(t, "10.0.0.1", node.Endpoint)
  38. assert.Equal(t, "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", node.PublicKey)
  39. assert.Equal(t, "01:02:03:04:05:06", node.MacAddress)
  40. assert.Equal(t, int32(51821), node.ListenPort)
  41. assert.NotNil(t, node.Name)
  42. assert.Equal(t, "skynet", node.Network)
  43. assert.Equal(t, "nm-skynet", node.Interface)
  44. }
  45. func TestDeleteNode(t *testing.T) {
  46. deleteNet(t)
  47. createNet()
  48. node := createTestNode()
  49. t.Run("NodeExists", func(t *testing.T) {
  50. deleted, err := DeleteNode(node.MacAddress, node.Network)
  51. assert.Nil(t, err)
  52. assert.True(t, deleted)
  53. })
  54. t.Run("NonExistantNode", func(t *testing.T) {
  55. deleted, err := DeleteNode(node.MacAddress, node.Network)
  56. assert.Nil(t, err)
  57. assert.False(t, deleted)
  58. })
  59. }
  60. func TestGetNode(t *testing.T) {
  61. deleteNet(t)
  62. createNet()
  63. node := createTestNode()
  64. t.Run("NodeExists", func(t *testing.T) {
  65. response, err := GetNode(node.MacAddress, node.Network)
  66. assert.Nil(t, err)
  67. assert.Equal(t, "10.0.0.1", response.Endpoint)
  68. assert.Equal(t, "DM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", response.PublicKey)
  69. assert.Equal(t, "01:02:03:04:05:06", response.MacAddress)
  70. assert.Equal(t, int32(51821), response.ListenPort)
  71. assert.NotNil(t, response.Name)
  72. assert.Equal(t, "skynet", response.Network)
  73. assert.Equal(t, "nm-skynet", response.Interface)
  74. })
  75. t.Run("BadMac", func(t *testing.T) {
  76. response, err := GetNode("01:02:03:04:05:07", node.Network)
  77. assert.NotNil(t, err)
  78. assert.Equal(t, models.Node{}, response)
  79. assert.Equal(t, "mongo: no documents in result", err.Error())
  80. })
  81. t.Run("BadNetwork", func(t *testing.T) {
  82. response, err := GetNode(node.MacAddress, "badnet")
  83. assert.NotNil(t, err)
  84. assert.Equal(t, models.Node{}, response)
  85. assert.Equal(t, "mongo: no documents in result", err.Error())
  86. })
  87. t.Run("NoNode", func(t *testing.T) {
  88. _, _ = DeleteNode("01:02:03:04:05:06", "skynet")
  89. response, err := GetNode(node.MacAddress, node.Network)
  90. assert.NotNil(t, err)
  91. assert.Equal(t, models.Node{}, response)
  92. assert.Equal(t, "mongo: no documents in result", err.Error())
  93. })
  94. }
  95. func TestGetPeerList(t *testing.T) {
  96. deleteNet(t)
  97. createNet()
  98. _ = createTestNode()
  99. //createnode := models.Node{PublicKey: "RM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.0.0.2", MacAddress: "02:02:03:04:05:06", Password: "password", Network: "skynet"}
  100. //_, _ = CreateNode(createnode, "skynet")
  101. t.Run("PeerExist", func(t *testing.T) {
  102. peers, err := GetPeersList("skynet")
  103. assert.Nil(t, err)
  104. assert.NotEqual(t, []models.PeersResponse(nil), peers)
  105. t.Log(peers)
  106. })
  107. t.Run("NoNodes", func(t *testing.T) {
  108. _, _ = DeleteNode("01:02:03:04:05:06", "skynet")
  109. peers, err := GetPeersList("skynet")
  110. assert.Nil(t, err)
  111. assert.Equal(t, []models.PeersResponse(nil), peers)
  112. t.Log(peers)
  113. })
  114. }
  115. func TestNodeCheckIn(t *testing.T) {
  116. deleteNet(t)
  117. createNet()
  118. node := createTestNode()
  119. time.Sleep(time.Second * 1)
  120. expectedResponse := models.CheckInResponse{false, false, false, false, false, "", false}
  121. t.Run("BadNet", func(t *testing.T) {
  122. response, err := NodeCheckIn(node, "badnet")
  123. assert.NotNil(t, err)
  124. assert.Contains(t, err.Error(), "Couldnt retrieve Network badnet: ")
  125. assert.Equal(t, expectedResponse, response)
  126. })
  127. t.Run("BadNode", func(t *testing.T) {
  128. badnode := models.Node{PublicKey: "RM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.0.0.2", MacAddress: "02:02:03:04:05:06", Password: "password", Network: "skynet"}
  129. response, err := NodeCheckIn(badnode, "skynet")
  130. assert.NotNil(t, err)
  131. assert.Contains(t, err.Error(), "Couldnt Get Node 02:02:03:04:05:06")
  132. assert.Equal(t, expectedResponse, response)
  133. })
  134. t.Run("NoUpdatesNeeded", func(t *testing.T) {
  135. expectedResponse := models.CheckInResponse{true, false, false, false, false, "", false}
  136. response, err := NodeCheckIn(node, node.Network)
  137. assert.Nil(t, err)
  138. assert.Equal(t, expectedResponse, response)
  139. })
  140. t.Run("NodePending", func(t *testing.T) {
  141. // create Pending Node
  142. createnode := models.Node{PublicKey: "RM5qhLAE20PG9BbfBCger+Ac9D2NDOwCtY1rbYDLf34=", Endpoint: "10.0.0.2", MacAddress: "01:02:03:04:05:07", Password: "password", Network: "skynet", IsPending: true}
  143. pendingNode, _ := CreateNode(createnode, "skynet")
  144. expectedResponse.IsPending = true
  145. response, err := NodeCheckIn(pendingNode, "skynet")
  146. assert.NotNil(t, err)
  147. assert.Contains(t, err.Error(), "Node checking in is still pending: 01:02:03:04:05:07")
  148. assert.Equal(t, expectedResponse, response)
  149. })
  150. t.Run("ConfigUpdateRequired", func(t *testing.T) {
  151. err := TimestampNode(node, false, false, true)
  152. assert.Nil(t, err)
  153. expectedResponse.NeedConfigUpdate = true
  154. expectedResponse.Success = true
  155. response, err := NodeCheckIn(node, "skynet")
  156. assert.Nil(t, err)
  157. assert.Equal(t, true, response.Success)
  158. assert.Equal(t, true, response.NeedConfigUpdate)
  159. })
  160. t.Run("PeerUpdateRequired", func(t *testing.T) {
  161. var nodeUpdate models.NodeUpdate
  162. newtime := time.Now().Add(time.Hour * -24).Unix()
  163. nodeUpdate.LastPeerUpdate = newtime
  164. _, err := UpdateNode(nodeUpdate, node)
  165. assert.Nil(t, err)
  166. response, err := NodeCheckIn(node, "skynet")
  167. assert.Nil(t, err)
  168. assert.Equal(t, true, response.Success)
  169. assert.Equal(t, true, response.NeedPeerUpdate)
  170. })
  171. t.Run("KeyUpdateRequired", func(t *testing.T) {
  172. var network models.Network
  173. newtime := time.Now().Add(time.Hour * 24).Unix()
  174. t.Log(newtime, time.Now().Unix())
  175. //this is cheating; but can't find away to update timestamp through existing api
  176. collection := mongoconn.Client.Database("netmaker").Collection("networks")
  177. ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
  178. filter := bson.M{"netid": "skynet"}
  179. update := bson.D{
  180. {"$set", bson.D{
  181. {"keyupdatetimestamp", newtime},
  182. }},
  183. }
  184. defer cancel()
  185. err := collection.FindOneAndUpdate(ctx, filter, update).Decode(&network)
  186. assert.Nil(t, err)
  187. response, err := NodeCheckIn(node, "skynet")
  188. assert.Nil(t, err)
  189. assert.Equal(t, true, response.Success)
  190. assert.Equal(t, true, response.NeedKeyUpdate)
  191. })
  192. t.Run("DeleteNeeded", func(t *testing.T) {
  193. var nodeUpdate models.NodeUpdate
  194. newtime := time.Now().Add(time.Hour * -24).Unix()
  195. nodeUpdate.ExpirationDateTime = newtime
  196. _, err := UpdateNode(nodeUpdate, node)
  197. assert.Nil(t, err)
  198. response, err := NodeCheckIn(node, "skynet")
  199. assert.Nil(t, err)
  200. assert.Equal(t, true, response.Success)
  201. assert.Equal(t, true, response.NeedDelete)
  202. })
  203. }
  204. func TestSetNetworkNodesLastModified(t *testing.T) {
  205. deleteNet(t)
  206. createNet()
  207. t.Run("InvalidNetwork", func(t *testing.T) {
  208. err := SetNetworkNodesLastModified("badnet")
  209. assert.NotNil(t, err)
  210. assert.Equal(t, "mongo: no documents in result", err.Error())
  211. })
  212. t.Run("NetworkExists", func(t *testing.T) {
  213. err := SetNetworkNodesLastModified("skynet")
  214. assert.Nil(t, err)
  215. })
  216. }
  217. func TestTimestampNode(t *testing.T) {
  218. deleteNet(t)
  219. createNet()
  220. node := createTestNode()
  221. time.Sleep(time.Second * 1)
  222. before, err := GetNode(node.MacAddress, node.Network)
  223. assert.Nil(t, err)
  224. t.Run("UpdateCheckIn", func(t *testing.T) {
  225. err = TimestampNode(node, true, false, false)
  226. assert.Nil(t, err)
  227. after, err := GetNode(node.MacAddress, node.Network)
  228. assert.Nil(t, err)
  229. assert.Greater(t, after.LastCheckIn, before.LastCheckIn)
  230. })
  231. t.Run("UpdatePeers", func(t *testing.T) {
  232. err = TimestampNode(node, false, true, false)
  233. assert.Nil(t, err)
  234. after, err := GetNode(node.MacAddress, node.Network)
  235. assert.Nil(t, err)
  236. assert.Greater(t, after.LastPeerUpdate, before.LastPeerUpdate)
  237. })
  238. t.Run("UpdateLastModified", func(t *testing.T) {
  239. err = TimestampNode(node, false, false, true)
  240. assert.Nil(t, err)
  241. after, err := GetNode(node.MacAddress, node.Network)
  242. assert.Nil(t, err)
  243. assert.Greater(t, after.LastModified, before.LastModified)
  244. })
  245. t.Run("InvalidNode", func(t *testing.T) {
  246. node.MacAddress = "01:02:03:04:05:08"
  247. err = TimestampNode(node, true, true, true)
  248. assert.NotNil(t, err)
  249. assert.Equal(t, "mongo: no documents in result", err.Error())
  250. })
  251. }
  252. func TestUpdateNode(t *testing.T) {
  253. deleteNet(t)
  254. createNet()
  255. node := createTestNode()
  256. var update models.NodeUpdate
  257. update.MacAddress = "01:02:03:04:05:06"
  258. update.Name = "helloworld"
  259. newnode, err := UpdateNode(update, node)
  260. assert.Nil(t, err)
  261. assert.Equal(t, update.Name, newnode.Name)
  262. }
  263. func TestValidateNodeCreate(t *testing.T) {
  264. cases := []NodeValidationTC{
  265. // NodeValidationTC{
  266. // testname: "EmptyAddress",
  267. // node: models.Node{
  268. // Address: "",
  269. // },
  270. // errorMessage: "Field validation for 'Endpoint' failed on the 'address_check' tag",
  271. // },
  272. NodeValidationTC{
  273. testname: "BadAddress",
  274. node: models.Node{
  275. Address: "256.0.0.1",
  276. },
  277. errorMessage: "Field validation for 'Address' failed on the 'ipv4' tag",
  278. },
  279. NodeValidationTC{
  280. testname: "BadAddress6",
  281. node: models.Node{
  282. Address6: "2607::abcd:efgh::1",
  283. },
  284. errorMessage: "Field validation for 'Address6' failed on the 'ipv6' tag",
  285. },
  286. NodeValidationTC{
  287. testname: "BadLocalAddress",
  288. node: models.Node{
  289. LocalAddress: "10.0.200.300",
  290. },
  291. errorMessage: "Field validation for 'LocalAddress' failed on the 'ip' tag",
  292. },
  293. NodeValidationTC{
  294. testname: "InvalidName",
  295. node: models.Node{
  296. Name: "mynode*",
  297. },
  298. errorMessage: "Field validation for 'Name' failed on the 'alphanum' tag",
  299. },
  300. NodeValidationTC{
  301. testname: "NameTooLong",
  302. node: models.Node{
  303. Name: "mynodexmynode",
  304. },
  305. errorMessage: "Field validation for 'Name' failed on the 'max' tag",
  306. },
  307. NodeValidationTC{
  308. testname: "ListenPortMin",
  309. node: models.Node{
  310. ListenPort: 1023,
  311. },
  312. errorMessage: "Field validation for 'ListenPort' failed on the 'min' tag",
  313. },
  314. NodeValidationTC{
  315. testname: "ListenPortMax",
  316. node: models.Node{
  317. ListenPort: 65536,
  318. },
  319. errorMessage: "Field validation for 'ListenPort' failed on the 'max' tag",
  320. },
  321. NodeValidationTC{
  322. testname: "PublicKeyEmpty",
  323. node: models.Node{
  324. PublicKey: "",
  325. },
  326. errorMessage: "Field validation for 'PublicKey' failed on the 'required' tag",
  327. },
  328. NodeValidationTC{
  329. testname: "PublicKeyInvalid",
  330. node: models.Node{
  331. PublicKey: "junk%key",
  332. },
  333. errorMessage: "Field validation for 'PublicKey' failed on the 'base64' tag",
  334. },
  335. NodeValidationTC{
  336. testname: "EndpointInvalid",
  337. node: models.Node{
  338. Endpoint: "10.2.0.300",
  339. },
  340. errorMessage: "Field validation for 'Endpoint' failed on the 'ip' tag",
  341. },
  342. NodeValidationTC{
  343. testname: "EndpointEmpty",
  344. node: models.Node{
  345. Endpoint: "",
  346. },
  347. errorMessage: "Field validation for 'Endpoint' failed on the 'required' tag",
  348. },
  349. NodeValidationTC{
  350. testname: "PersistentKeepaliveMax",
  351. node: models.Node{
  352. PersistentKeepalive: 1001,
  353. },
  354. errorMessage: "Field validation for 'PersistentKeepalive' failed on the 'max' tag",
  355. },
  356. NodeValidationTC{
  357. testname: "MacAddressInvalid",
  358. node: models.Node{
  359. MacAddress: "01:02:03:04:05",
  360. },
  361. errorMessage: "Field validation for 'MacAddress' failed on the 'mac' tag",
  362. },
  363. NodeValidationTC{
  364. testname: "MacAddressMissing",
  365. node: models.Node{
  366. MacAddress: "",
  367. },
  368. errorMessage: "Field validation for 'MacAddress' failed on the 'required' tag",
  369. },
  370. NodeValidationTC{
  371. testname: "EmptyPassword",
  372. node: models.Node{
  373. Password: "",
  374. },
  375. errorMessage: "Field validation for 'Password' failed on the 'required' tag",
  376. },
  377. NodeValidationTC{
  378. testname: "ShortPassword",
  379. node: models.Node{
  380. Password: "1234",
  381. },
  382. errorMessage: "Field validation for 'Password' failed on the 'min' tag",
  383. },
  384. NodeValidationTC{
  385. testname: "NoNetwork",
  386. node: models.Node{
  387. Network: "badnet",
  388. },
  389. errorMessage: "Field validation for 'Network' failed on the 'network_exists' tag",
  390. },
  391. }
  392. for _, tc := range cases {
  393. t.Run(tc.testname, func(t *testing.T) {
  394. err := ValidateNodeCreate("skynet", tc.node)
  395. assert.NotNil(t, err)
  396. assert.Contains(t, err.Error(), tc.errorMessage)
  397. })
  398. }
  399. t.Run("MacAddresUnique", func(t *testing.T) {
  400. createNet()
  401. node := models.Node{MacAddress: "01:02:03:04:05:06", Network: "skynet"}
  402. _, err := CreateNode(node, "skynet")
  403. assert.Nil(t, err)
  404. err = ValidateNodeCreate("skynet", node)
  405. assert.NotNil(t, err)
  406. assert.Contains(t, err.Error(), "Field validation for 'MacAddress' failed on the 'macaddress_unique' tag")
  407. })
  408. t.Run("EmptyAddress", func(t *testing.T) {
  409. node := models.Node{Address: ""}
  410. err := ValidateNodeCreate("skynet", node)
  411. assert.NotNil(t, err)
  412. assert.NotContains(t, err.Error(), "Field validation for 'Address' failed on the 'ipv4' tag")
  413. })
  414. }
  415. func TestValidateNodeUpdate(t *testing.T) {
  416. //cases
  417. cases := []NodeValidationUpdateTC{
  418. NodeValidationUpdateTC{
  419. testname: "BadAddress",
  420. node: models.NodeUpdate{
  421. Address: "256.0.0.1",
  422. },
  423. errorMessage: "Field validation for 'Address' failed on the 'ip' tag",
  424. },
  425. NodeValidationUpdateTC{
  426. testname: "BadAddress6",
  427. node: models.NodeUpdate{
  428. Address6: "2607::abcd:efgh::1",
  429. },
  430. errorMessage: "Field validation for 'Address6' failed on the 'ipv6' tag",
  431. },
  432. NodeValidationUpdateTC{
  433. testname: "BadLocalAddress",
  434. node: models.NodeUpdate{
  435. LocalAddress: "10.0.200.300",
  436. },
  437. errorMessage: "Field validation for 'LocalAddress' failed on the 'ip' tag",
  438. },
  439. NodeValidationUpdateTC{
  440. testname: "InvalidName",
  441. node: models.NodeUpdate{
  442. Name: "mynode*",
  443. },
  444. errorMessage: "Field validation for 'Name' failed on the 'alphanum' tag",
  445. },
  446. NodeValidationUpdateTC{
  447. testname: "NameTooLong",
  448. node: models.NodeUpdate{
  449. Name: "mynodexmynode",
  450. },
  451. errorMessage: "Field validation for 'Name' failed on the 'max' tag",
  452. },
  453. NodeValidationUpdateTC{
  454. testname: "ListenPortMin",
  455. node: models.NodeUpdate{
  456. ListenPort: 1023,
  457. },
  458. errorMessage: "Field validation for 'ListenPort' failed on the 'min' tag",
  459. },
  460. NodeValidationUpdateTC{
  461. testname: "ListenPortMax",
  462. node: models.NodeUpdate{
  463. ListenPort: 65536,
  464. },
  465. errorMessage: "Field validation for 'ListenPort' failed on the 'max' tag",
  466. },
  467. NodeValidationUpdateTC{
  468. testname: "PublicKeyInvalid",
  469. node: models.NodeUpdate{
  470. PublicKey: "bad&key",
  471. },
  472. errorMessage: "Field validation for 'PublicKey' failed on the 'base64' tag",
  473. },
  474. NodeValidationUpdateTC{
  475. testname: "EndpointInvalid",
  476. node: models.NodeUpdate{
  477. Endpoint: "10.2.0.300",
  478. },
  479. errorMessage: "Field validation for 'Endpoint' failed on the 'ip' tag",
  480. },
  481. NodeValidationUpdateTC{
  482. testname: "PersistentKeepaliveMax",
  483. node: models.NodeUpdate{
  484. PersistentKeepalive: 1001,
  485. },
  486. errorMessage: "Field validation for 'PersistentKeepalive' failed on the 'max' tag",
  487. },
  488. NodeValidationUpdateTC{
  489. testname: "MacAddressInvalid",
  490. node: models.NodeUpdate{
  491. MacAddress: "01:02:03:04:05",
  492. },
  493. errorMessage: "Field validation for 'MacAddress' failed on the 'mac' tag",
  494. },
  495. NodeValidationUpdateTC{
  496. testname: "MacAddressMissing",
  497. node: models.NodeUpdate{
  498. MacAddress: "",
  499. },
  500. errorMessage: "Field validation for 'MacAddress' failed on the 'required' tag",
  501. },
  502. NodeValidationUpdateTC{
  503. testname: "ShortPassword",
  504. node: models.NodeUpdate{
  505. Password: "1234",
  506. },
  507. errorMessage: "Field validation for 'Password' failed on the 'min' tag",
  508. },
  509. NodeValidationUpdateTC{
  510. testname: "NoNetwork",
  511. node: models.NodeUpdate{
  512. Network: "badnet",
  513. },
  514. errorMessage: "Field validation for 'Network' failed on the 'network_exists' tag",
  515. },
  516. }
  517. for _, tc := range cases {
  518. t.Run(tc.testname, func(t *testing.T) {
  519. err := ValidateNodeUpdate("skynet", tc.node)
  520. assert.NotNil(t, err)
  521. assert.Contains(t, err.Error(), tc.errorMessage)
  522. })
  523. }
  524. }