provision_handler.go 27 KB

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