hosts.go 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289
  1. package controller
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "github.com/gorilla/mux"
  7. "github.com/gravitl/netmaker/logger"
  8. "github.com/gravitl/netmaker/logic"
  9. "github.com/gravitl/netmaker/models"
  10. "github.com/gravitl/netmaker/mq"
  11. "github.com/gravitl/netmaker/servercfg"
  12. )
  13. type hostNetworksUpdatePayload struct {
  14. Networks []string `json:"networks"`
  15. }
  16. func hostHandlers(r *mux.Router) {
  17. r.HandleFunc("/api/hosts", logic.SecurityCheck(true, http.HandlerFunc(getHosts))).Methods(http.MethodGet)
  18. r.HandleFunc("/api/hosts/{hostid}", logic.SecurityCheck(true, http.HandlerFunc(updateHost))).Methods(http.MethodPut)
  19. r.HandleFunc("/api/hosts/{hostid}", logic.SecurityCheck(true, http.HandlerFunc(deleteHost))).Methods(http.MethodDelete)
  20. r.HandleFunc("/api/hosts/{hostid}/networks", logic.SecurityCheck(true, http.HandlerFunc(updateHostNetworks))).Methods(http.MethodPut)
  21. r.HandleFunc("/api/hosts/{hostid}/relay", logic.SecurityCheck(false, http.HandlerFunc(createHostRelay))).Methods(http.MethodPost)
  22. r.HandleFunc("/api/hosts/{hostid}/relay", logic.SecurityCheck(false, http.HandlerFunc(deleteHostRelay))).Methods(http.MethodDelete)
  23. }
  24. // swagger:route GET /api/hosts hosts getHosts
  25. //
  26. // Lists all hosts.
  27. //
  28. // Schemes: https
  29. //
  30. // Security:
  31. // oauth
  32. //
  33. // Responses:
  34. // 200: getHostsSliceResponse
  35. func getHosts(w http.ResponseWriter, r *http.Request) {
  36. currentHosts, err := logic.GetAllHosts()
  37. if err != nil {
  38. logger.Log(0, r.Header.Get("user"), "failed to fetch hosts: ", err.Error())
  39. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  40. return
  41. }
  42. // return JSON/API formatted hosts
  43. apiHosts := logic.GetAllHostsAPI(currentHosts[:])
  44. logger.Log(2, r.Header.Get("user"), "fetched all hosts")
  45. w.WriteHeader(http.StatusOK)
  46. json.NewEncoder(w).Encode(apiHosts)
  47. }
  48. // swagger:route PUT /api/hosts/{hostid} hosts updateHost
  49. //
  50. // Updates a Netclient host on Netmaker server.
  51. //
  52. // Schemes: https
  53. //
  54. // Security:
  55. // oauth
  56. //
  57. // Responses:
  58. // 200: updateHostResponse
  59. func updateHost(w http.ResponseWriter, r *http.Request) {
  60. var newHostData models.ApiHost
  61. err := json.NewDecoder(r.Body).Decode(&newHostData)
  62. if err != nil {
  63. logger.Log(0, r.Header.Get("user"), "failed to update a host:", err.Error())
  64. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  65. return
  66. }
  67. // confirm host exists
  68. currHost, err := logic.GetHost(newHostData.ID)
  69. if err != nil {
  70. logger.Log(0, r.Header.Get("user"), "failed to update a host:", err.Error())
  71. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  72. return
  73. }
  74. newHost := newHostData.ConvertAPIHostToNMHost(currHost)
  75. logic.UpdateHost(newHost, currHost) // update the in memory struct values
  76. if err = logic.UpsertHost(newHost); err != nil {
  77. logger.Log(0, r.Header.Get("user"), "failed to update a host:", err.Error())
  78. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  79. return
  80. }
  81. newNetworks := logic.GetHostNetworks(newHost.ID.String())
  82. if len(newNetworks) > 0 {
  83. if err = mq.ModifyClient(&mq.MqClient{
  84. ID: currHost.ID.String(),
  85. Text: currHost.Name,
  86. Networks: newNetworks,
  87. }); err != nil {
  88. logger.Log(0, r.Header.Get("user"), "failed to update host networks roles in DynSec:", err.Error())
  89. }
  90. }
  91. apiHostData := newHost.ConvertNMHostToAPI()
  92. logger.Log(2, r.Header.Get("user"), "updated host", newHost.ID.String())
  93. w.WriteHeader(http.StatusOK)
  94. json.NewEncoder(w).Encode(apiHostData)
  95. }
  96. // swagger:route DELETE /api/hosts/{hostid} hosts deleteHost
  97. //
  98. // Deletes a Netclient host from Netmaker server.
  99. //
  100. // Schemes: https
  101. //
  102. // Security:
  103. // oauth
  104. //
  105. // Responses:
  106. // 200: deleteHostResponse
  107. func deleteHost(w http.ResponseWriter, r *http.Request) {
  108. var params = mux.Vars(r)
  109. hostid := params["hostid"]
  110. // confirm host exists
  111. currHost, err := logic.GetHost(hostid)
  112. if err != nil {
  113. logger.Log(0, r.Header.Get("user"), "failed to delete a host:", err.Error())
  114. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  115. return
  116. }
  117. if err = logic.RemoveHost(currHost); err != nil {
  118. logger.Log(0, r.Header.Get("user"), "failed to delete a host:", err.Error())
  119. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  120. return
  121. }
  122. if err = mq.DeleteMqClient(currHost.ID.String()); err != nil {
  123. logger.Log(0, "error removing DynSec credentials for host:", currHost.Name, err.Error())
  124. }
  125. apiHostData := currHost.ConvertNMHostToAPI()
  126. logger.Log(2, r.Header.Get("user"), "removed host", currHost.Name)
  127. w.WriteHeader(http.StatusOK)
  128. json.NewEncoder(w).Encode(apiHostData)
  129. }
  130. // swagger:route PUT /api/hosts hosts updateHostNetworks
  131. //
  132. // Given a list of networks, a host is updated accordingly.
  133. //
  134. // Schemes: https
  135. //
  136. // Security:
  137. // oauth
  138. //
  139. // Responses:
  140. // 200: updateHostNetworks
  141. func updateHostNetworks(w http.ResponseWriter, r *http.Request) {
  142. var payload hostNetworksUpdatePayload
  143. err := json.NewDecoder(r.Body).Decode(&payload)
  144. if err != nil {
  145. logger.Log(0, r.Header.Get("user"), "failed to update host networks:", err.Error())
  146. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  147. return
  148. }
  149. // confirm host exists
  150. var params = mux.Vars(r)
  151. hostid := params["hostid"]
  152. currHost, err := logic.GetHost(hostid)
  153. if err != nil {
  154. logger.Log(0, r.Header.Get("user"), "failed to find host:", err.Error())
  155. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  156. return
  157. }
  158. if err = logic.UpdateHostNetworks(currHost, servercfg.GetServer(), payload.Networks[:]); err != nil {
  159. logger.Log(0, r.Header.Get("user"), "failed to update host networks:", err.Error())
  160. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  161. return
  162. }
  163. if err = mq.ModifyClient(&mq.MqClient{
  164. ID: currHost.ID.String(),
  165. Text: currHost.Name,
  166. Networks: payload.Networks,
  167. }); err != nil {
  168. logger.Log(0, r.Header.Get("user"), "failed to update host networks roles in DynSec:", err.Error())
  169. }
  170. logger.Log(2, r.Header.Get("user"), "updated host networks", currHost.Name)
  171. w.WriteHeader(http.StatusOK)
  172. json.NewEncoder(w).Encode(payload)
  173. }
  174. // swagger:route POST /api/hosts/{hostid}/relay hosts createHostRelay
  175. //
  176. // Create a relay.
  177. //
  178. // Schemes: https
  179. //
  180. // Security:
  181. // oauth
  182. //
  183. // Responses:
  184. // 200: nodeResponse
  185. func createHostRelay(w http.ResponseWriter, r *http.Request) {
  186. var relay models.HostRelayRequest
  187. var params = mux.Vars(r)
  188. w.Header().Set("Content-Type", "application/json")
  189. err := json.NewDecoder(r.Body).Decode(&relay)
  190. if err != nil {
  191. logger.Log(0, r.Header.Get("user"), "error decoding request body: ", err.Error())
  192. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  193. return
  194. }
  195. relay.HostID = params["hostid"]
  196. relayHost, _, err := logic.CreateHostRelay(relay)
  197. if err != nil {
  198. logger.Log(0, r.Header.Get("user"),
  199. fmt.Sprintf("failed to create relay on host [%s]: %v", relay.HostID, err))
  200. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "internal"))
  201. return
  202. }
  203. logger.Log(1, r.Header.Get("user"), "created relay on host", relay.HostID)
  204. // for _, relayedHost := range relayedHosts {
  205. // err = mq.PublishSingleHostUpdate(&relayedHost)
  206. // if err != nil {
  207. // logger.Log(1, "error sending update to relayed host ", relayedHost.ID.String(), ": ", err.Error())
  208. // }
  209. // }
  210. // // publish host update for relayhost
  211. // err = mq.PublishSingleHostUpdate(relayHost)
  212. // if err != nil {
  213. // logger.Log(1, "error sending update to relay host ", relayHost.ID.String(), ": ", err.Error())
  214. // }
  215. go func() {
  216. if err := mq.PublishPeerUpdate("", false); err != nil {
  217. logger.Log(0, "fail to publish peer update: ", err.Error())
  218. }
  219. }()
  220. apiHostData := relayHost.ConvertNMHostToAPI()
  221. w.WriteHeader(http.StatusOK)
  222. json.NewEncoder(w).Encode(apiHostData)
  223. }
  224. // swagger:route DELETE /api/hosts/{hostid}/relay hosts deleteHostRelay
  225. //
  226. // Remove a relay.
  227. //
  228. // Schemes: https
  229. //
  230. // Security:
  231. // oauth
  232. //
  233. // Responses:
  234. // 200: nodeResponse
  235. func deleteHostRelay(w http.ResponseWriter, r *http.Request) {
  236. w.Header().Set("Content-Type", "application/json")
  237. var params = mux.Vars(r)
  238. hostid := params["hostid"]
  239. relayHost, _, err := logic.DeleteHostRelay(hostid)
  240. if err != nil {
  241. logger.Log(0, r.Header.Get("user"), "error decoding request body: ", err.Error())
  242. logic.ReturnErrorResponse(w, r, logic.FormatError(err, "badrequest"))
  243. return
  244. }
  245. logger.Log(1, r.Header.Get("user"), "deleted relay host", hostid)
  246. // for _, relayedHost := range relayedHosts {
  247. // err = mq.PublishSingleHostUpdate(&relayedHost)
  248. // if err != nil {
  249. // logger.Log(1, "error sending update to relayed host ", relayedHost.ID.String(), ": ", err.Error())
  250. // }
  251. // }
  252. // err = mq.PublishSingleHostUpdate(relayHost)
  253. // if err != nil {
  254. // logger.Log(1, "error sending update to relayed host ", relayHost.ID.String(), ": ", err.Error())
  255. // }
  256. go func() {
  257. if err := mq.PublishPeerUpdate("", false); err != nil {
  258. logger.Log(0, "fail to publish peer update: ", err.Error())
  259. }
  260. }()
  261. apiHostData := relayHost.ConvertNMHostToAPI()
  262. w.WriteHeader(http.StatusOK)
  263. json.NewEncoder(w).Encode(apiHostData)
  264. }