provision_handler.go 26 KB

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