provision_handler.go 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142
  1. package api
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "strconv"
  6. "github.com/go-chi/chi"
  7. "github.com/porter-dev/porter/internal/analytics"
  8. "github.com/porter-dev/porter/internal/forms"
  9. "github.com/porter-dev/porter/internal/kubernetes"
  10. "github.com/porter-dev/porter/internal/kubernetes/provisioner"
  11. "github.com/porter-dev/porter/internal/models"
  12. "github.com/porter-dev/porter/internal/adapter"
  13. )
  14. // HandleProvisionTestInfra will create a test resource by deploying a provisioner
  15. // container pod
  16. func (app *App) HandleProvisionTestInfra(w http.ResponseWriter, r *http.Request) {
  17. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  18. userID, err := app.getUserIDFromRequest(r)
  19. if err != nil || projID == 0 {
  20. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  21. return
  22. }
  23. form := &forms.CreateTestInfra{
  24. ProjectID: uint(projID),
  25. }
  26. // decode from JSON to form value
  27. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  28. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  29. return
  30. }
  31. // convert the form to an aws infra instance
  32. infra, err := form.ToInfra()
  33. if err != nil {
  34. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  35. return
  36. }
  37. infra.CreatedByUserID = userID
  38. // handle write to the database
  39. infra, err = app.Repo.Infra.CreateInfra(infra)
  40. if err != nil {
  41. app.handleErrorDataWrite(err, w)
  42. return
  43. }
  44. _, err = app.ProvisionerAgent.ProvisionTest(
  45. uint(projID),
  46. infra,
  47. *app.Repo,
  48. provisioner.Apply,
  49. &app.DBConf,
  50. app.RedisConf,
  51. app.ServerConf.ProvisionerImageTag,
  52. app.ServerConf.ProvisionerImagePullSecret,
  53. )
  54. if err != nil {
  55. infra.Status = models.StatusError
  56. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  57. app.handleErrorInternal(err, w)
  58. return
  59. }
  60. app.Logger.Info().Msgf("New test infra created: %d", infra.ID)
  61. w.WriteHeader(http.StatusCreated)
  62. infraExt := infra.Externalize()
  63. if err := json.NewEncoder(w).Encode(infraExt); err != nil {
  64. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  65. return
  66. }
  67. }
  68. // HandleDestroyTestInfra destroys test infra
  69. func (app *App) HandleDestroyTestInfra(w http.ResponseWriter, r *http.Request) {
  70. // get path parameters
  71. infraID, err := strconv.ParseUint(chi.URLParam(r, "infra_id"), 10, 64)
  72. if err != nil {
  73. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  74. return
  75. }
  76. // read infra to get id
  77. infra, err := app.Repo.Infra.ReadInfra(uint(infraID))
  78. if err != nil {
  79. app.handleErrorDataRead(err, w)
  80. return
  81. }
  82. // launch provisioning destruction pod
  83. agent, err := kubernetes.GetAgentInClusterConfig()
  84. if err != nil {
  85. infra.Status = models.StatusError
  86. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  87. app.handleErrorDataRead(err, w)
  88. return
  89. }
  90. // mark infra for deletion
  91. infra.Status = models.StatusDestroying
  92. infra, err = app.Repo.Infra.UpdateInfra(infra)
  93. if err != nil {
  94. app.handleErrorDataWrite(err, w)
  95. return
  96. }
  97. _, err = agent.ProvisionTest(
  98. infra.ProjectID,
  99. infra,
  100. *app.Repo,
  101. provisioner.Destroy,
  102. &app.DBConf,
  103. app.RedisConf,
  104. app.ServerConf.ProvisionerImageTag,
  105. app.ServerConf.ProvisionerImagePullSecret,
  106. )
  107. if err != nil {
  108. app.handleErrorInternal(err, w)
  109. return
  110. }
  111. app.Logger.Info().Msgf("Test infra marked for destruction: %d", infra.ID)
  112. w.WriteHeader(http.StatusOK)
  113. }
  114. // HandleProvisionAWSECRInfra provisions a new aws ECR instance for a project
  115. func (app *App) HandleProvisionAWSECRInfra(w http.ResponseWriter, r *http.Request) {
  116. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  117. userID, err := app.getUserIDFromRequest(r)
  118. if err != nil || projID == 0 {
  119. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  120. return
  121. }
  122. form := &forms.CreateECRInfra{
  123. ProjectID: uint(projID),
  124. }
  125. // decode from JSON to form value
  126. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  127. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  128. return
  129. }
  130. // validate the form
  131. if err := app.validator.Struct(form); err != nil {
  132. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  133. return
  134. }
  135. // convert the form to an aws infra instance
  136. infra, err := form.ToInfra()
  137. if err != nil {
  138. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  139. return
  140. }
  141. infra.CreatedByUserID = userID
  142. // handle write to the database
  143. infra, err = app.Repo.Infra.CreateInfra(infra)
  144. if err != nil {
  145. app.handleErrorDataWrite(err, w)
  146. return
  147. }
  148. awsInt, err := app.Repo.AWSIntegration.ReadAWSIntegration(infra.AWSIntegrationID)
  149. if err != nil {
  150. infra.Status = models.StatusError
  151. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  152. app.handleErrorDataRead(err, w)
  153. return
  154. }
  155. // launch provisioning pod
  156. _, err = app.ProvisionerAgent.ProvisionECR(
  157. uint(projID),
  158. awsInt,
  159. form.ECRName,
  160. *app.Repo,
  161. infra,
  162. provisioner.Apply,
  163. &app.DBConf,
  164. app.RedisConf,
  165. app.ServerConf.ProvisionerImageTag,
  166. app.ServerConf.ProvisionerImagePullSecret,
  167. )
  168. if err != nil {
  169. infra.Status = models.StatusError
  170. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  171. app.handleErrorInternal(err, w)
  172. return
  173. }
  174. app.Logger.Info().Msgf("New aws ecr infra created: %d", infra.ID)
  175. app.AnalyticsClient.Track(analytics.RegistryProvisioningStartTrack(
  176. &analytics.RegistryProvisioningStartTrackOpts{
  177. ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(userID, uint(projID)),
  178. RegistryType: models.InfraECR,
  179. InfraID: infra.ID,
  180. },
  181. ))
  182. w.WriteHeader(http.StatusCreated)
  183. infraExt := infra.Externalize()
  184. if err := json.NewEncoder(w).Encode(infraExt); err != nil {
  185. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  186. return
  187. }
  188. }
  189. // HandleDestroyAWSECRInfra destroys ecr infra
  190. func (app *App) HandleDestroyAWSECRInfra(w http.ResponseWriter, r *http.Request) {
  191. // get path parameters
  192. infraID, err := strconv.ParseUint(chi.URLParam(r, "infra_id"), 10, 64)
  193. if err != nil {
  194. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  195. return
  196. }
  197. // read infra to get id
  198. infra, err := app.Repo.Infra.ReadInfra(uint(infraID))
  199. if err != nil {
  200. app.handleErrorDataRead(err, w)
  201. return
  202. }
  203. awsInt, err := app.Repo.AWSIntegration.ReadAWSIntegration(infra.AWSIntegrationID)
  204. form := &forms.DestroyECRInfra{}
  205. // decode from JSON to form value
  206. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  207. infra.Status = models.StatusError
  208. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  209. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  210. return
  211. }
  212. // validate the form
  213. if err := app.validator.Struct(form); err != nil {
  214. infra.Status = models.StatusError
  215. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  216. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  217. return
  218. }
  219. // launch provisioning destruction pod
  220. // mark infra for deletion
  221. infra.Status = models.StatusDestroying
  222. infra, err = app.Repo.Infra.UpdateInfra(infra)
  223. if err != nil {
  224. app.handleErrorDataWrite(err, w)
  225. return
  226. }
  227. _, err = app.ProvisionerAgent.ProvisionECR(
  228. infra.ProjectID,
  229. awsInt,
  230. form.ECRName,
  231. *app.Repo,
  232. infra,
  233. provisioner.Destroy,
  234. &app.DBConf,
  235. app.RedisConf,
  236. app.ServerConf.ProvisionerImageTag,
  237. app.ServerConf.ProvisionerImagePullSecret,
  238. )
  239. if err != nil {
  240. app.handleErrorInternal(err, w)
  241. return
  242. }
  243. app.Logger.Info().Msgf("AWS ECR infra marked for destruction: %d", infra.ID)
  244. w.WriteHeader(http.StatusOK)
  245. }
  246. // HandleProvisionAWSEKSInfra provisions a new aws EKS instance for a project
  247. func (app *App) HandleProvisionAWSEKSInfra(w http.ResponseWriter, r *http.Request) {
  248. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  249. userID, err := app.getUserIDFromRequest(r)
  250. if err != nil || projID == 0 {
  251. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  252. return
  253. }
  254. form := &forms.CreateEKSInfra{
  255. ProjectID: uint(projID),
  256. }
  257. // decode from JSON to form value
  258. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  259. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  260. return
  261. }
  262. // validate the form
  263. if err := app.validator.Struct(form); err != nil {
  264. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  265. return
  266. }
  267. // convert the form to an aws infra instance
  268. infra, err := form.ToInfra()
  269. if err != nil {
  270. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  271. return
  272. }
  273. infra.CreatedByUserID = userID
  274. // handle write to the database
  275. infra, err = app.Repo.Infra.CreateInfra(infra)
  276. if err != nil {
  277. app.handleErrorDataWrite(err, w)
  278. return
  279. }
  280. awsInt, err := app.Repo.AWSIntegration.ReadAWSIntegration(infra.AWSIntegrationID)
  281. if err != nil {
  282. infra.Status = models.StatusError
  283. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  284. app.handleErrorDataRead(err, w)
  285. return
  286. }
  287. // launch provisioning pod
  288. _, err = app.ProvisionerAgent.ProvisionEKS(
  289. uint(projID),
  290. awsInt,
  291. form.EKSName,
  292. form.MachineType,
  293. *app.Repo,
  294. infra,
  295. provisioner.Apply,
  296. &app.DBConf,
  297. app.RedisConf,
  298. app.ServerConf.ProvisionerImageTag,
  299. app.ServerConf.ProvisionerImagePullSecret,
  300. )
  301. if err != nil {
  302. infra.Status = models.StatusError
  303. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  304. app.handleErrorInternal(err, w)
  305. return
  306. }
  307. app.Logger.Info().Msgf("New aws eks infra created: %d", infra.ID)
  308. app.AnalyticsClient.Track(analytics.ClusterProvisioningStartTrack(
  309. &analytics.ClusterProvisioningStartTrackOpts{
  310. ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(userID, uint(projID)),
  311. ClusterType: models.InfraEKS,
  312. InfraID: infra.ID,
  313. },
  314. ))
  315. w.WriteHeader(http.StatusCreated)
  316. infraExt := infra.Externalize()
  317. if err := json.NewEncoder(w).Encode(infraExt); err != nil {
  318. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  319. return
  320. }
  321. }
  322. // HandleDestroyAWSEKSInfra destroys eks infra
  323. func (app *App) HandleDestroyAWSEKSInfra(w http.ResponseWriter, r *http.Request) {
  324. // get path parameters
  325. infraID, err := strconv.ParseUint(chi.URLParam(r, "infra_id"), 10, 64)
  326. // userID, err := app.getUserIDFromRequest(r)
  327. if err != nil {
  328. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  329. return
  330. }
  331. // read infra to get id
  332. infra, err := app.Repo.Infra.ReadInfra(uint(infraID))
  333. if err != nil {
  334. app.handleErrorDataRead(err, w)
  335. return
  336. }
  337. awsInt, err := app.Repo.AWSIntegration.ReadAWSIntegration(infra.AWSIntegrationID)
  338. form := &forms.DestroyEKSInfra{}
  339. // decode from JSON to form value
  340. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  341. infra.Status = models.StatusError
  342. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  343. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  344. return
  345. }
  346. // validate the form
  347. if err := app.validator.Struct(form); err != nil {
  348. infra.Status = models.StatusError
  349. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  350. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  351. return
  352. }
  353. // launch provisioning destruction pod
  354. // mark infra for deletion
  355. infra.Status = models.StatusDestroying
  356. infra, err = app.Repo.Infra.UpdateInfra(infra)
  357. if err != nil {
  358. app.handleErrorDataWrite(err, w)
  359. return
  360. }
  361. _, err = app.ProvisionerAgent.ProvisionEKS(
  362. infra.ProjectID,
  363. awsInt,
  364. form.EKSName,
  365. "",
  366. *app.Repo,
  367. infra,
  368. provisioner.Destroy,
  369. &app.DBConf,
  370. app.RedisConf,
  371. app.ServerConf.ProvisionerImageTag,
  372. app.ServerConf.ProvisionerImagePullSecret,
  373. )
  374. if err != nil {
  375. app.handleErrorInternal(err, w)
  376. return
  377. }
  378. app.Logger.Info().Msgf("AWS EKS infra marked for destruction: %d", infra.ID)
  379. w.WriteHeader(http.StatusOK)
  380. }
  381. // HandleProvisionGCPGCRInfra enables GCR for a project
  382. func (app *App) HandleProvisionGCPGCRInfra(w http.ResponseWriter, r *http.Request) {
  383. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  384. userID, err := app.getUserIDFromRequest(r)
  385. if err != nil || projID == 0 {
  386. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  387. return
  388. }
  389. form := &forms.CreateGCRInfra{
  390. ProjectID: uint(projID),
  391. }
  392. // decode from JSON to form value
  393. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  394. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  395. return
  396. }
  397. // validate the form
  398. if err := app.validator.Struct(form); err != nil {
  399. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  400. return
  401. }
  402. // convert the form to an aws infra instance
  403. infra, err := form.ToInfra()
  404. if err != nil {
  405. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  406. return
  407. }
  408. infra.CreatedByUserID = userID
  409. // handle write to the database
  410. infra, err = app.Repo.Infra.CreateInfra(infra)
  411. if err != nil {
  412. app.handleErrorDataWrite(err, w)
  413. return
  414. }
  415. gcpInt, err := app.Repo.GCPIntegration.ReadGCPIntegration(infra.GCPIntegrationID)
  416. if err != nil {
  417. infra.Status = models.StatusError
  418. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  419. app.handleErrorDataRead(err, w)
  420. return
  421. }
  422. // launch provisioning pod
  423. _, err = app.ProvisionerAgent.ProvisionGCR(
  424. uint(projID),
  425. gcpInt,
  426. *app.Repo,
  427. infra,
  428. provisioner.Apply,
  429. &app.DBConf,
  430. app.RedisConf,
  431. app.ServerConf.ProvisionerImageTag,
  432. app.ServerConf.ProvisionerImagePullSecret,
  433. )
  434. if err != nil {
  435. infra.Status = models.StatusError
  436. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  437. app.handleErrorInternal(err, w)
  438. return
  439. }
  440. app.Logger.Info().Msgf("New gcp gcr infra created: %d", infra.ID)
  441. app.AnalyticsClient.Track(analytics.RegistryProvisioningStartTrack(
  442. &analytics.RegistryProvisioningStartTrackOpts{
  443. ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(userID, uint(projID)),
  444. RegistryType: models.InfraGCR,
  445. InfraID: infra.ID,
  446. },
  447. ))
  448. w.WriteHeader(http.StatusCreated)
  449. infraExt := infra.Externalize()
  450. if err := json.NewEncoder(w).Encode(infraExt); err != nil {
  451. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  452. return
  453. }
  454. }
  455. // HandleProvisionGCPGKEInfra provisions a new GKE instance for a project
  456. func (app *App) HandleProvisionGCPGKEInfra(w http.ResponseWriter, r *http.Request) {
  457. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  458. userID, err := app.getUserIDFromRequest(r)
  459. if err != nil || projID == 0 {
  460. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  461. return
  462. }
  463. form := &forms.CreateGKEInfra{
  464. ProjectID: uint(projID),
  465. }
  466. // decode from JSON to form value
  467. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  468. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  469. return
  470. }
  471. // validate the form
  472. if err := app.validator.Struct(form); err != nil {
  473. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  474. return
  475. }
  476. // convert the form to an aws infra instance
  477. infra, err := form.ToInfra()
  478. if err != nil {
  479. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  480. return
  481. }
  482. infra.CreatedByUserID = userID
  483. // handle write to the database
  484. infra, err = app.Repo.Infra.CreateInfra(infra)
  485. if err != nil {
  486. app.handleErrorDataWrite(err, w)
  487. return
  488. }
  489. gcpInt, err := app.Repo.GCPIntegration.ReadGCPIntegration(infra.GCPIntegrationID)
  490. if err != nil {
  491. infra.Status = models.StatusError
  492. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  493. app.handleErrorDataRead(err, w)
  494. return
  495. }
  496. // launch provisioning pod
  497. _, err = app.ProvisionerAgent.ProvisionGKE(
  498. uint(projID),
  499. gcpInt,
  500. form.GKEName,
  501. *app.Repo,
  502. infra,
  503. provisioner.Apply,
  504. &app.DBConf,
  505. app.RedisConf,
  506. app.ServerConf.ProvisionerImageTag,
  507. app.ServerConf.ProvisionerImagePullSecret,
  508. )
  509. if err != nil {
  510. infra.Status = models.StatusError
  511. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  512. app.handleErrorInternal(err, w)
  513. return
  514. }
  515. app.Logger.Info().Msgf("New gcp gke infra created: %d", infra.ID)
  516. app.AnalyticsClient.Track(analytics.ClusterProvisioningStartTrack(
  517. &analytics.ClusterProvisioningStartTrackOpts{
  518. ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(userID, uint(projID)),
  519. ClusterType: models.InfraGKE,
  520. InfraID: infra.ID,
  521. },
  522. ))
  523. w.WriteHeader(http.StatusCreated)
  524. infraExt := infra.Externalize()
  525. if err := json.NewEncoder(w).Encode(infraExt); err != nil {
  526. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  527. return
  528. }
  529. }
  530. // HandleDestroyGCPGKEInfra destroys gke infra
  531. func (app *App) HandleDestroyGCPGKEInfra(w http.ResponseWriter, r *http.Request) {
  532. // get path parameters
  533. infraID, err := strconv.ParseUint(chi.URLParam(r, "infra_id"), 10, 64)
  534. // userID, err := app.getUserIDFromRequest(r)
  535. if err != nil {
  536. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  537. return
  538. }
  539. // read infra to get id
  540. infra, err := app.Repo.Infra.ReadInfra(uint(infraID))
  541. if err != nil {
  542. app.handleErrorDataRead(err, w)
  543. return
  544. }
  545. gcpInt, err := app.Repo.GCPIntegration.ReadGCPIntegration(infra.GCPIntegrationID)
  546. form := &forms.DestroyGKEInfra{}
  547. // decode from JSON to form value
  548. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  549. infra.Status = models.StatusError
  550. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  551. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  552. return
  553. }
  554. // validate the form
  555. if err := app.validator.Struct(form); err != nil {
  556. infra.Status = models.StatusError
  557. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  558. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  559. return
  560. }
  561. // launch provisioning destruction pod
  562. // mark infra for deletion
  563. infra.Status = models.StatusDestroying
  564. infra, err = app.Repo.Infra.UpdateInfra(infra)
  565. if err != nil {
  566. app.handleErrorDataWrite(err, w)
  567. return
  568. }
  569. _, err = app.ProvisionerAgent.ProvisionGKE(
  570. infra.ProjectID,
  571. gcpInt,
  572. form.GKEName,
  573. *app.Repo,
  574. infra,
  575. provisioner.Destroy,
  576. &app.DBConf,
  577. app.RedisConf,
  578. app.ServerConf.ProvisionerImageTag,
  579. app.ServerConf.ProvisionerImagePullSecret,
  580. )
  581. if err != nil {
  582. app.handleErrorInternal(err, w)
  583. return
  584. }
  585. app.Logger.Info().Msgf("GCP GKE infra marked for destruction: %d", infra.ID)
  586. w.WriteHeader(http.StatusOK)
  587. }
  588. // HandleGetProvisioningLogs returns real-time logs of the provisioning process via websockets
  589. func (app *App) HandleGetProvisioningLogs(w http.ResponseWriter, r *http.Request) {
  590. // get path parameters
  591. infraID, err := strconv.ParseUint(chi.URLParam(r, "infra_id"), 10, 64)
  592. if err != nil {
  593. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  594. return
  595. }
  596. // read infra to get id
  597. infra, err := app.Repo.Infra.ReadInfra(uint(infraID))
  598. if err != nil {
  599. app.handleErrorDataRead(err, w)
  600. return
  601. }
  602. streamName := infra.GetUniqueName()
  603. upgrader.CheckOrigin = func(r *http.Request) bool { return true }
  604. // upgrade to websocket.
  605. conn, err := upgrader.Upgrade(w, r, nil)
  606. if err != nil {
  607. app.handleErrorUpgradeWebsocket(err, w)
  608. }
  609. client, err := adapter.NewRedisClient(app.RedisConf)
  610. if err != nil {
  611. app.handleErrorInternal(err, w)
  612. return
  613. }
  614. err = provisioner.ResourceStream(client, streamName, conn)
  615. if err != nil {
  616. app.handleErrorWebsocketWrite(err, w)
  617. return
  618. }
  619. }
  620. // HandleProvisionDODOCRInfra provisions a new digitalocean DOCR instance for a project
  621. func (app *App) HandleProvisionDODOCRInfra(w http.ResponseWriter, r *http.Request) {
  622. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  623. userID, err := app.getUserIDFromRequest(r)
  624. if err != nil || projID == 0 {
  625. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  626. return
  627. }
  628. form := &forms.CreateDOCRInfra{
  629. ProjectID: uint(projID),
  630. }
  631. // decode from JSON to form value
  632. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  633. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  634. return
  635. }
  636. // validate the form
  637. if err := app.validator.Struct(form); err != nil {
  638. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  639. return
  640. }
  641. // convert the form to an aws infra instance
  642. infra, err := form.ToInfra()
  643. if err != nil {
  644. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  645. return
  646. }
  647. infra.CreatedByUserID = userID
  648. // handle write to the database
  649. infra, err = app.Repo.Infra.CreateInfra(infra)
  650. if err != nil {
  651. app.handleErrorDataWrite(err, w)
  652. return
  653. }
  654. oauthInt, err := app.Repo.OAuthIntegration.ReadOAuthIntegration(infra.DOIntegrationID)
  655. if err != nil {
  656. infra.Status = models.StatusError
  657. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  658. app.handleErrorDataRead(err, w)
  659. return
  660. }
  661. // launch provisioning pod
  662. _, err = app.ProvisionerAgent.ProvisionDOCR(
  663. uint(projID),
  664. oauthInt,
  665. app.DOConf,
  666. *app.Repo,
  667. form.DOCRName,
  668. form.DOCRSubscriptionTier,
  669. infra,
  670. provisioner.Apply,
  671. &app.DBConf,
  672. app.RedisConf,
  673. app.ServerConf.ProvisionerImageTag,
  674. app.ServerConf.ProvisionerImagePullSecret,
  675. )
  676. if err != nil {
  677. infra.Status = models.StatusError
  678. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  679. app.handleErrorInternal(err, w)
  680. return
  681. }
  682. app.Logger.Info().Msgf("New do docr infra created: %d", infra.ID)
  683. app.AnalyticsClient.Track(analytics.RegistryProvisioningStartTrack(
  684. &analytics.RegistryProvisioningStartTrackOpts{
  685. ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(userID, uint(projID)),
  686. RegistryType: models.InfraDOCR,
  687. InfraID: infra.ID,
  688. },
  689. ))
  690. w.WriteHeader(http.StatusCreated)
  691. infraExt := infra.Externalize()
  692. if err := json.NewEncoder(w).Encode(infraExt); err != nil {
  693. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  694. return
  695. }
  696. }
  697. // HandleDestroyAWSDOCRInfra destroys docr infra
  698. func (app *App) HandleDestroyDODOCRInfra(w http.ResponseWriter, r *http.Request) {
  699. // get path parameters
  700. infraID, err := strconv.ParseUint(chi.URLParam(r, "infra_id"), 10, 64)
  701. if err != nil {
  702. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  703. return
  704. }
  705. // read infra to get id
  706. infra, err := app.Repo.Infra.ReadInfra(uint(infraID))
  707. if err != nil {
  708. app.handleErrorDataRead(err, w)
  709. return
  710. }
  711. oauthInt, err := app.Repo.OAuthIntegration.ReadOAuthIntegration(infra.DOIntegrationID)
  712. form := &forms.DestroyDOCRInfra{}
  713. // decode from JSON to form value
  714. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  715. infra.Status = models.StatusError
  716. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  717. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  718. return
  719. }
  720. // validate the form
  721. if err := app.validator.Struct(form); err != nil {
  722. infra.Status = models.StatusError
  723. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  724. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  725. return
  726. }
  727. // launch provisioning destruction pod
  728. // mark infra for deletion
  729. infra.Status = models.StatusDestroying
  730. infra, err = app.Repo.Infra.UpdateInfra(infra)
  731. if err != nil {
  732. app.handleErrorDataWrite(err, w)
  733. return
  734. }
  735. _, err = app.ProvisionerAgent.ProvisionDOCR(
  736. infra.ProjectID,
  737. oauthInt,
  738. app.DOConf,
  739. *app.Repo,
  740. form.DOCRName,
  741. "basic", // this doesn't matter for destroy
  742. infra,
  743. provisioner.Destroy,
  744. &app.DBConf,
  745. app.RedisConf,
  746. app.ServerConf.ProvisionerImageTag,
  747. app.ServerConf.ProvisionerImagePullSecret,
  748. )
  749. if err != nil {
  750. app.handleErrorInternal(err, w)
  751. return
  752. }
  753. app.Logger.Info().Msgf("DO DOCR infra marked for destruction: %d", infra.ID)
  754. w.WriteHeader(http.StatusOK)
  755. }
  756. // HandleProvisionDODOKSInfra provisions a new DO DOKS instance for a project
  757. func (app *App) HandleProvisionDODOKSInfra(w http.ResponseWriter, r *http.Request) {
  758. projID, err := strconv.ParseUint(chi.URLParam(r, "project_id"), 0, 64)
  759. userID, err := app.getUserIDFromRequest(r)
  760. if err != nil || projID == 0 {
  761. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  762. return
  763. }
  764. form := &forms.CreateDOKSInfra{
  765. ProjectID: uint(projID),
  766. }
  767. // decode from JSON to form value
  768. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  769. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  770. return
  771. }
  772. // validate the form
  773. if err := app.validator.Struct(form); err != nil {
  774. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  775. return
  776. }
  777. // convert the form to an aws infra instance
  778. infra, err := form.ToInfra()
  779. if err != nil {
  780. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  781. return
  782. }
  783. infra.CreatedByUserID = userID
  784. // handle write to the database
  785. infra, err = app.Repo.Infra.CreateInfra(infra)
  786. if err != nil {
  787. app.handleErrorDataWrite(err, w)
  788. return
  789. }
  790. oauthInt, err := app.Repo.OAuthIntegration.ReadOAuthIntegration(infra.DOIntegrationID)
  791. if err != nil {
  792. infra.Status = models.StatusError
  793. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  794. app.handleErrorDataRead(err, w)
  795. return
  796. }
  797. // launch provisioning pod
  798. _, err = app.ProvisionerAgent.ProvisionDOKS(
  799. uint(projID),
  800. oauthInt,
  801. app.DOConf,
  802. *app.Repo,
  803. form.DORegion,
  804. form.DOKSName,
  805. infra,
  806. provisioner.Apply,
  807. &app.DBConf,
  808. app.RedisConf,
  809. app.ServerConf.ProvisionerImageTag,
  810. app.ServerConf.ProvisionerImagePullSecret,
  811. )
  812. if err != nil {
  813. infra.Status = models.StatusError
  814. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  815. app.handleErrorInternal(err, w)
  816. return
  817. }
  818. app.Logger.Info().Msgf("New do doks infra created: %d", infra.ID)
  819. app.AnalyticsClient.Track(analytics.ClusterProvisioningStartTrack(
  820. &analytics.ClusterProvisioningStartTrackOpts{
  821. ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(userID, uint(projID)),
  822. ClusterType: models.InfraDOKS,
  823. InfraID: infra.ID,
  824. },
  825. ))
  826. w.WriteHeader(http.StatusCreated)
  827. infraExt := infra.Externalize()
  828. if err := json.NewEncoder(w).Encode(infraExt); err != nil {
  829. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  830. return
  831. }
  832. }
  833. // HandleDestroyDODOKSInfra destroys DOKS infra
  834. func (app *App) HandleDestroyDODOKSInfra(w http.ResponseWriter, r *http.Request) {
  835. // get path parameters
  836. infraID, err := strconv.ParseUint(chi.URLParam(r, "infra_id"), 10, 64)
  837. if err != nil {
  838. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  839. return
  840. }
  841. // read infra to get id
  842. infra, err := app.Repo.Infra.ReadInfra(uint(infraID))
  843. if err != nil {
  844. app.handleErrorDataRead(err, w)
  845. return
  846. }
  847. oauthInt, err := app.Repo.OAuthIntegration.ReadOAuthIntegration(infra.DOIntegrationID)
  848. form := &forms.DestroyDOKSInfra{}
  849. // decode from JSON to form value
  850. if err := json.NewDecoder(r.Body).Decode(form); err != nil {
  851. infra.Status = models.StatusError
  852. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  853. app.handleErrorFormDecoding(err, ErrProjectDecode, w)
  854. return
  855. }
  856. // validate the form
  857. if err := app.validator.Struct(form); err != nil {
  858. infra.Status = models.StatusError
  859. infra, _ = app.Repo.Infra.UpdateInfra(infra)
  860. app.handleErrorFormValidation(err, ErrProjectValidateFields, w)
  861. return
  862. }
  863. // launch provisioning destruction pod
  864. // mark infra for deletion
  865. infra.Status = models.StatusDestroying
  866. infra, err = app.Repo.Infra.UpdateInfra(infra)
  867. if err != nil {
  868. app.handleErrorDataWrite(err, w)
  869. return
  870. }
  871. _, err = app.ProvisionerAgent.ProvisionDOKS(
  872. infra.ProjectID,
  873. oauthInt,
  874. app.DOConf,
  875. *app.Repo,
  876. "nyc1",
  877. form.DOKSName,
  878. infra,
  879. provisioner.Destroy,
  880. &app.DBConf,
  881. app.RedisConf,
  882. app.ServerConf.ProvisionerImageTag,
  883. app.ServerConf.ProvisionerImagePullSecret,
  884. )
  885. if err != nil {
  886. app.handleErrorInternal(err, w)
  887. return
  888. }
  889. app.Logger.Info().Msgf("DO DOKS infra marked for destruction: %d", infra.ID)
  890. w.WriteHeader(http.StatusOK)
  891. }