network.go 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629
  1. package controller
  2. import (
  3. "encoding/json"
  4. "errors"
  5. "fmt"
  6. "net"
  7. "net/http"
  8. "strings"
  9. "github.com/google/uuid"
  10. "github.com/gorilla/mux"
  11. "golang.org/x/exp/slog"
  12. "github.com/gravitl/netmaker/database"
  13. "github.com/gravitl/netmaker/logger"
  14. "github.com/gravitl/netmaker/logic"
  15. "github.com/gravitl/netmaker/logic/acls"
  16. "github.com/gravitl/netmaker/models"
  17. "github.com/gravitl/netmaker/mq"
  18. "github.com/gravitl/netmaker/servercfg"
  19. )
  20. func networkHandlers(r *mux.Router) {
  21. r.HandleFunc("/api/networks", logic.SecurityCheck(true, http.HandlerFunc(getNetworks))).
  22. Methods(http.MethodGet)
  23. r.HandleFunc("/api/v1/networks/stats", logic.SecurityCheck(true, http.HandlerFunc(getNetworksStats))).
  24. Methods(http.MethodGet)
  25. r.HandleFunc("/api/networks", logic.SecurityCheck(true, checkFreeTierLimits(limitChoiceNetworks, http.HandlerFunc(createNetwork)))).
  26. Methods(http.MethodPost)
  27. r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(true, http.HandlerFunc(getNetwork))).
  28. Methods(http.MethodGet)
  29. r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(true, http.HandlerFunc(deleteNetwork))).
  30. Methods(http.MethodDelete)
  31. r.HandleFunc("/api/networks/{networkname}", logic.SecurityCheck(true, http.HandlerFunc(updateNetwork))).
  32. Methods(http.MethodPut)
  33. // ACLs
  34. r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(updateNetworkACL))).
  35. Methods(http.MethodPut)
  36. r.HandleFunc("/api/networks/{networkname}/acls/v2", logic.SecurityCheck(true, http.HandlerFunc(updateNetworkACLv2))).
  37. Methods(http.MethodPut)
  38. r.HandleFunc("/api/networks/{networkname}/acls", logic.SecurityCheck(true, http.HandlerFunc(getNetworkACL))).
  39. Methods(http.MethodGet)
  40. }
  41. // @Summary Lists all networks
  42. // @Router /api/networks [get]
  43. // @Tags Networks
  44. // @Security oauth
  45. // @Produce json
  46. // @Success 200 {object} models.Network
  47. // @Failure 500 {object} models.ErrorResponse
  48. func getNetworks(w http.ResponseWriter, r *http.Request) {
  49. var err error
  50. allnetworks, err := logic.GetNetworks()
  51. if err != nil && !database.IsEmptyRecord(err) {
  52. slog.Error("failed to fetch networks", "error", err.Error())
  53. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  54. return
  55. }
  56. if r.Header.Get("ismaster") != "yes" {
  57. username := r.Header.Get("user")
  58. user, err := logic.GetUser(username)
  59. if err != nil {
  60. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  61. return
  62. }
  63. allnetworks = logic.FilterNetworksByRole(allnetworks, *user)
  64. }
  65. logger.Log(2, r.Header.Get("user"), "fetched networks.")
  66. logic.SortNetworks(allnetworks[:])
  67. w.WriteHeader(http.StatusOK)
  68. json.NewEncoder(w).Encode(allnetworks)
  69. }
  70. // @Summary Lists all networks with stats
  71. // @Router /api/v1/networks/stats [get]
  72. // @Tags Networks
  73. // @Security oauth
  74. // @Produce json
  75. // @Success 200 {object} models.SuccessResponse
  76. // @Failure 500 {object} models.ErrorResponse
  77. func getNetworksStats(w http.ResponseWriter, r *http.Request) {
  78. var err error
  79. allnetworks, err := logic.GetNetworks()
  80. if err != nil && !database.IsEmptyRecord(err) {
  81. slog.Error("failed to fetch networks", "error", err.Error())
  82. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  83. return
  84. }
  85. if r.Header.Get("ismaster") != "yes" {
  86. username := r.Header.Get("user")
  87. user, err := logic.GetUser(username)
  88. if err != nil {
  89. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  90. return
  91. }
  92. allnetworks = logic.FilterNetworksByRole(allnetworks, *user)
  93. }
  94. allNodes, err := logic.GetAllNodes()
  95. if err != nil {
  96. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  97. return
  98. }
  99. netstats := []models.NetworkStatResp{}
  100. logic.SortNetworks(allnetworks[:])
  101. for _, network := range allnetworks {
  102. netstats = append(netstats, models.NetworkStatResp{
  103. Network: network,
  104. Hosts: len(logic.GetNetworkNodesMemory(allNodes, network.NetID)),
  105. })
  106. }
  107. logger.Log(2, r.Header.Get("user"), "fetched networks.")
  108. logic.ReturnSuccessResponseWithJson(w, r, netstats, "fetched networks with stats")
  109. }
  110. // @Summary Get a network
  111. // @Router /api/networks/{networkname} [get]
  112. // @Tags Networks
  113. // @Security oauth
  114. // @Param networkname path string true "Network name"
  115. // @Produce json
  116. // @Success 200 {object} models.Network
  117. // @Failure 500 {object} models.ErrorResponse
  118. func getNetwork(w http.ResponseWriter, r *http.Request) {
  119. // set header.
  120. w.Header().Set("Content-Type", "application/json")
  121. var params = mux.Vars(r)
  122. netname := params["networkname"]
  123. network, err := logic.GetNetwork(netname)
  124. if err != nil {
  125. logger.Log(0, r.Header.Get("user"), fmt.Sprintf("failed to fetch network [%s] info: %v",
  126. netname, err))
  127. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  128. return
  129. }
  130. logger.Log(2, r.Header.Get("user"), "fetched network", netname)
  131. w.WriteHeader(http.StatusOK)
  132. json.NewEncoder(w).Encode(network)
  133. }
  134. // @Summary Update a network ACL (Access Control List)
  135. // @Router /api/networks/{networkname}/acls [put]
  136. // @Tags Networks
  137. // @Security oauth
  138. // @Param networkname path string true "Network name"
  139. // @Param body body acls.ACLContainer true "ACL container"
  140. // @Produce json
  141. // @Success 200 {object} acls.ACLContainer
  142. // @Failure 400 {object} models.ErrorResponse
  143. // @Failure 500 {object} models.ErrorResponse
  144. func updateNetworkACL(w http.ResponseWriter, r *http.Request) {
  145. w.Header().Set("Content-Type", "application/json")
  146. var params = mux.Vars(r)
  147. netname := params["networkname"]
  148. var networkACLChange acls.ACLContainer
  149. networkACLChange, err := networkACLChange.Get(acls.ContainerID(netname))
  150. if err != nil {
  151. logger.Log(0, r.Header.Get("user"),
  152. fmt.Sprintf("failed to fetch ACLs for network [%s]: %v", netname, err))
  153. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  154. return
  155. }
  156. err = json.NewDecoder(r.Body).Decode(&networkACLChange)
  157. if err != nil {
  158. logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
  159. err.Error())
  160. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  161. return
  162. }
  163. newNetACL, err := networkACLChange.Save(acls.ContainerID(netname))
  164. if err != nil {
  165. logger.Log(0, r.Header.Get("user"),
  166. fmt.Sprintf("failed to update ACLs for network [%s]: %v", netname, err))
  167. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  168. return
  169. }
  170. logger.Log(1, r.Header.Get("user"), "updated ACLs for network", netname)
  171. // send peer updates
  172. go func() {
  173. if err = mq.PublishPeerUpdate(false); err != nil {
  174. logger.Log(0, "failed to publish peer update after ACL update on network:", netname)
  175. }
  176. }()
  177. w.WriteHeader(http.StatusOK)
  178. json.NewEncoder(w).Encode(newNetACL)
  179. }
  180. // @Summary Update a network ACL (Access Control List)
  181. // @Router /api/networks/{networkname}/acls/v2 [put]
  182. // @Tags Networks
  183. // @Security oauth
  184. // @Param networkname path string true "Network name"
  185. // @Param body body acls.ACLContainer true "ACL container"
  186. // @Produce json
  187. // @Success 200 {object} acls.ACLContainer
  188. // @Failure 400 {object} models.ErrorResponse
  189. // @Failure 500 {object} models.ErrorResponse
  190. func updateNetworkACLv2(w http.ResponseWriter, r *http.Request) {
  191. w.Header().Set("Content-Type", "application/json")
  192. var params = mux.Vars(r)
  193. netname := params["networkname"]
  194. var networkACLChange acls.ACLContainer
  195. networkACLChange, err := networkACLChange.Get(acls.ContainerID(netname))
  196. if err != nil {
  197. logger.Log(0, r.Header.Get("user"),
  198. fmt.Sprintf("failed to fetch ACLs for network [%s]: %v", netname, err))
  199. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  200. return
  201. }
  202. err = json.NewDecoder(r.Body).Decode(&networkACLChange)
  203. if err != nil {
  204. logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
  205. err.Error())
  206. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  207. return
  208. }
  209. // clone req body to use as return data successful update
  210. retData := make(acls.ACLContainer)
  211. data, err := json.Marshal(networkACLChange)
  212. if err != nil {
  213. slog.Error("failed to marshal networkACLChange whiles cloning", "error", err.Error())
  214. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  215. return
  216. }
  217. err = json.Unmarshal(data, &retData)
  218. if err != nil {
  219. slog.Error("failed to unmarshal networkACLChange whiles cloning", "error", err.Error())
  220. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  221. return
  222. }
  223. allNodes, err := logic.GetAllNodes()
  224. if err != nil {
  225. slog.Error("failed to fetch all nodes", "error", err.Error())
  226. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  227. return
  228. }
  229. networkNodes := make([]models.Node, 0)
  230. for _, node := range allNodes {
  231. if node.Network == netname {
  232. networkNodes = append(networkNodes, node)
  233. }
  234. }
  235. networkNodesIdMap := make(map[string]models.Node)
  236. for _, node := range networkNodes {
  237. networkNodesIdMap[node.ID.String()] = node
  238. }
  239. networkClients, err := logic.GetNetworkExtClients(netname)
  240. if err != nil {
  241. slog.Error("failed to fetch network clients", "error", err.Error())
  242. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  243. return
  244. }
  245. networkClientsMap := make(map[string]models.ExtClient)
  246. for _, client := range networkClients {
  247. networkClientsMap[client.ClientID] = client
  248. }
  249. // keep track of ingress gateways to disconnect from their clients
  250. // this is required because PublishPeerUpdate only somehow does not stop communication
  251. // between blocked clients and their ingress
  252. assocClientsToDisconnectPerHost := make(map[uuid.UUID][]models.ExtClient)
  253. // update client acls and then, remove client acls from req data to pass to existing functions
  254. for id, acl := range networkACLChange {
  255. // for node acls
  256. if _, ok := networkNodesIdMap[string(id)]; ok {
  257. nodeId := string(id)
  258. // check acl update, then remove client entries
  259. for id2 := range acl {
  260. if _, ok := networkNodesIdMap[string(id2)]; !ok {
  261. // update client acl
  262. clientId := string(id2)
  263. if client, ok := networkClientsMap[clientId]; ok {
  264. if client.DeniedACLs == nil {
  265. client.DeniedACLs = make(map[string]struct{})
  266. }
  267. if acl[acls.AclID(clientId)] == acls.NotAllowed {
  268. client.DeniedACLs[nodeId] = struct{}{}
  269. } else {
  270. delete(client.DeniedACLs, string(nodeId))
  271. }
  272. networkClientsMap[clientId] = client
  273. }
  274. }
  275. }
  276. } else {
  277. // for client acls
  278. clientId := string(id)
  279. for id2 := range acl {
  280. if _, ok := networkNodesIdMap[string(id2)]; !ok {
  281. // update client acl
  282. clientId2 := string(id2)
  283. if client, ok := networkClientsMap[clientId]; ok {
  284. if client.DeniedACLs == nil {
  285. client.DeniedACLs = make(map[string]struct{})
  286. }
  287. {
  288. // TODO: review this when client-to-client acls are supported
  289. // if acl[acls.AclID(clientId2)] == acls.NotAllowed {
  290. // client.DeniedACLs[clientId2] = struct{}{}
  291. // } else {
  292. // delete(client.DeniedACLs, clientId2)
  293. // }
  294. delete(client.DeniedACLs, clientId2)
  295. }
  296. networkClientsMap[clientId] = client
  297. }
  298. } else {
  299. nodeId2 := string(id2)
  300. if networkClientsMap[clientId].IngressGatewayID == nodeId2 && acl[acls.AclID(nodeId2)] == acls.NotAllowed {
  301. assocClientsToDisconnectPerHost[networkNodesIdMap[nodeId2].HostID] = append(assocClientsToDisconnectPerHost[networkNodesIdMap[nodeId2].HostID], networkClientsMap[clientId])
  302. }
  303. }
  304. }
  305. }
  306. }
  307. // update each client in db for pro servers
  308. if servercfg.IsPro {
  309. for _, client := range networkClientsMap {
  310. client := client
  311. err := logic.DeleteExtClient(client.Network, client.ClientID)
  312. if err != nil {
  313. slog.Error(
  314. "failed to delete client during update",
  315. "client",
  316. client.ClientID,
  317. "error",
  318. err.Error(),
  319. )
  320. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  321. return
  322. }
  323. err = logic.SaveExtClient(&client)
  324. if err != nil {
  325. slog.Error(
  326. "failed to save client during update",
  327. "client",
  328. client.ClientID,
  329. "error",
  330. err.Error(),
  331. )
  332. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  333. return
  334. }
  335. }
  336. }
  337. _, err = networkACLChange.Save(acls.ContainerID(netname))
  338. if err != nil {
  339. logger.Log(0, r.Header.Get("user"),
  340. fmt.Sprintf("failed to update ACLs for network [%s]: %v", netname, err))
  341. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  342. return
  343. }
  344. logger.Log(1, r.Header.Get("user"), "updated ACLs for network", netname)
  345. // send peer updates
  346. go func() {
  347. if err = mq.PublishPeerUpdate(false); err != nil {
  348. logger.Log(0, "failed to publish peer update after ACL update on network:", netname)
  349. }
  350. // update ingress gateways of associated clients
  351. hosts, err := logic.GetAllHosts()
  352. if err != nil {
  353. slog.Error(
  354. "failed to fetch hosts after network ACL update. skipping publish extclients ACL",
  355. "network",
  356. netname,
  357. )
  358. return
  359. }
  360. hostsMap := make(map[uuid.UUID]models.Host)
  361. for _, host := range hosts {
  362. hostsMap[host.ID] = host
  363. }
  364. for hostId, clients := range assocClientsToDisconnectPerHost {
  365. if host, ok := hostsMap[hostId]; ok {
  366. if err = mq.PublishSingleHostPeerUpdate(&host, allNodes, nil, clients, false, nil); err != nil {
  367. slog.Error("failed to publish peer update to ingress after ACL update on network", "network", netname, "host", hostId)
  368. }
  369. }
  370. }
  371. }()
  372. w.WriteHeader(http.StatusOK)
  373. json.NewEncoder(w).Encode(networkACLChange)
  374. }
  375. // @Summary Get a network ACL (Access Control List)
  376. // @Router /api/networks/{networkname}/acls [get]
  377. // @Tags Networks
  378. // @Security oauth
  379. // @Param networkname path string true "Network name"
  380. // @Produce json
  381. // @Success 200 {object} acls.ACLContainer
  382. // @Failure 500 {object} models.ErrorResponse
  383. func getNetworkACL(w http.ResponseWriter, r *http.Request) {
  384. w.Header().Set("Content-Type", "application/json")
  385. var params = mux.Vars(r)
  386. netname := params["networkname"]
  387. var networkACL acls.ACLContainer
  388. networkACL, err := networkACL.Get(acls.ContainerID(netname))
  389. if err != nil {
  390. if database.IsEmptyRecord(err) {
  391. networkACL = acls.ACLContainer{}
  392. w.WriteHeader(http.StatusOK)
  393. json.NewEncoder(w).Encode(networkACL)
  394. return
  395. }
  396. logger.Log(0, r.Header.Get("user"),
  397. fmt.Sprintf("failed to fetch ACLs for network [%s]: %v", netname, err))
  398. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  399. return
  400. }
  401. logger.Log(2, r.Header.Get("user"), "fetched acl for network", netname)
  402. w.WriteHeader(http.StatusOK)
  403. json.NewEncoder(w).Encode(networkACL)
  404. }
  405. // @Summary Delete a network
  406. // @Router /api/networks/{networkname} [delete]
  407. // @Tags Networks
  408. // @Security oauth
  409. // @Param networkname path string true "Network name"
  410. // @Produce json
  411. // @Success 200 {object} models.SuccessResponse
  412. // @Failure 400 {object} models.ErrorResponse
  413. // @Failure 403 {object} models.ErrorResponse
  414. func deleteNetwork(w http.ResponseWriter, r *http.Request) {
  415. // Set header
  416. w.Header().Set("Content-Type", "application/json")
  417. var params = mux.Vars(r)
  418. network := params["networkname"]
  419. err := logic.DeleteNetwork(network)
  420. if err != nil {
  421. errtype := "badrequest"
  422. if strings.Contains(err.Error(), "Node check failed") {
  423. errtype = "forbidden"
  424. }
  425. logger.Log(0, r.Header.Get("user"),
  426. fmt.Sprintf("failed to delete network [%s]: %v", network, err))
  427. logic.ReturnErrorResponse(w, r, logic.FormatError(err, errtype))
  428. return
  429. }
  430. go logic.DeleteNetworkRoles(network)
  431. go logic.DeleteDefaultNetworkPolicies(models.NetworkID(network))
  432. //delete network from allocated ip map
  433. go logic.RemoveNetworkFromAllocatedIpMap(network)
  434. logger.Log(1, r.Header.Get("user"), "deleted network", network)
  435. w.WriteHeader(http.StatusOK)
  436. json.NewEncoder(w).Encode("success")
  437. }
  438. // @Summary Create a network
  439. // @Router /api/networks [post]
  440. // @Tags Networks
  441. // @Security oauth
  442. // @Param body body models.Network true "Network details"
  443. // @Produce json
  444. // @Success 200 {object} models.Network
  445. // @Failure 400 {object} models.ErrorResponse
  446. func createNetwork(w http.ResponseWriter, r *http.Request) {
  447. w.Header().Set("Content-Type", "application/json")
  448. var network models.Network
  449. // we decode our body request params
  450. err := json.NewDecoder(r.Body).Decode(&network)
  451. if err != nil {
  452. logger.Log(0, r.Header.Get("user"), "error decoding request body: ",
  453. err.Error())
  454. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  455. return
  456. }
  457. if len(network.NetID) > 32 {
  458. err := errors.New("network name shouldn't exceed 32 characters")
  459. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  460. err.Error())
  461. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  462. return
  463. }
  464. if network.AddressRange == "" && network.AddressRange6 == "" {
  465. err := errors.New("IPv4 or IPv6 CIDR required")
  466. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  467. err.Error())
  468. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  469. return
  470. }
  471. // validate address ranges: must be private
  472. if network.AddressRange != "" {
  473. _, _, err := net.ParseCIDR(network.AddressRange)
  474. if err != nil {
  475. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  476. err.Error())
  477. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  478. return
  479. }
  480. }
  481. if network.AddressRange6 != "" {
  482. _, _, err := net.ParseCIDR(network.AddressRange6)
  483. if err != nil {
  484. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  485. err.Error())
  486. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  487. return
  488. }
  489. }
  490. network, err = logic.CreateNetwork(network)
  491. if err != nil {
  492. logger.Log(0, r.Header.Get("user"), "failed to create network: ",
  493. err.Error())
  494. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  495. return
  496. }
  497. logic.CreateDefaultNetworkRolesAndGroups(models.NetworkID(network.NetID))
  498. logic.CreateDefaultAclNetworkPolicies(models.NetworkID(network.NetID))
  499. logic.CreateDefaultTags(models.NetworkID(network.NetID))
  500. //add new network to allocated ip map
  501. go logic.AddNetworkToAllocatedIpMap(network.NetID)
  502. go func() {
  503. defaultHosts := logic.GetDefaultHosts()
  504. for i := range defaultHosts {
  505. currHost := &defaultHosts[i]
  506. newNode, err := logic.UpdateHostNetwork(currHost, network.NetID, true)
  507. if err != nil {
  508. logger.Log(
  509. 0,
  510. r.Header.Get("user"),
  511. "failed to add host to network:",
  512. currHost.ID.String(),
  513. network.NetID,
  514. err.Error(),
  515. )
  516. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  517. return
  518. }
  519. logger.Log(1, "added new node", newNode.ID.String(), "to host", currHost.Name)
  520. if err = mq.HostUpdate(&models.HostUpdate{
  521. Action: models.JoinHostToNetwork,
  522. Host: *currHost,
  523. Node: *newNode,
  524. }); err != nil {
  525. logger.Log(
  526. 0,
  527. r.Header.Get("user"),
  528. "failed to add host to network:",
  529. currHost.ID.String(),
  530. network.NetID,
  531. err.Error(),
  532. )
  533. }
  534. // make host failover
  535. logic.CreateFailOver(*newNode)
  536. // make host remote access gateway
  537. logic.CreateIngressGateway(network.NetID, newNode.ID.String(), models.IngressRequest{})
  538. }
  539. // send peer updates
  540. if err = mq.PublishPeerUpdate(false); err != nil {
  541. logger.Log(1, "failed to publish peer update for default hosts after network is added")
  542. }
  543. }()
  544. logger.Log(1, r.Header.Get("user"), "created network", network.NetID)
  545. w.WriteHeader(http.StatusOK)
  546. json.NewEncoder(w).Encode(network)
  547. }
  548. // @Summary Update network settings
  549. // @Router /api/networks/{networkname} [put]
  550. // @Tags Networks
  551. // @Security oauth
  552. // @Param networkname path string true "Network name"
  553. // @Param body body models.Network true "Network details"
  554. // @Produce json
  555. // @Success 200 {object} models.Network
  556. // @Failure 400 {object} models.ErrorResponse
  557. func updateNetwork(w http.ResponseWriter, r *http.Request) {
  558. w.Header().Set("Content-Type", "application/json")
  559. var payload models.Network
  560. // we decode our body request params
  561. err := json.NewDecoder(r.Body).Decode(&payload)
  562. if err != nil {
  563. slog.Info("error decoding request body", "user", r.Header.Get("user"), "err", err)
  564. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  565. return
  566. }
  567. netOld1, err := logic.GetNetwork(payload.NetID)
  568. if err != nil {
  569. slog.Info("error fetching network", "user", r.Header.Get("user"), "err", err)
  570. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  571. return
  572. }
  573. // partial update
  574. netOld2 := netOld1
  575. _, _, _, err = logic.UpdateNetwork(&netOld1, &netOld2)
  576. if err != nil {
  577. slog.Info("failed to update network", "user", r.Header.Get("user"), "err", err)
  578. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  579. return
  580. }
  581. slog.Info("updated network", "network", payload.NetID, "user", r.Header.Get("user"))
  582. w.WriteHeader(http.StatusOK)
  583. json.NewEncoder(w).Encode(payload)
  584. }