provision_handler.go 25 KB

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