common_test.go 16 KB

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