delete.go 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350
  1. package infra
  2. import (
  3. "encoding/json"
  4. "net/http"
  5. "github.com/porter-dev/porter/api/server/handlers"
  6. "github.com/porter-dev/porter/api/server/handlers/provision"
  7. "github.com/porter-dev/porter/api/server/shared"
  8. "github.com/porter-dev/porter/api/server/shared/apierrors"
  9. "github.com/porter-dev/porter/api/server/shared/config"
  10. "github.com/porter-dev/porter/api/types"
  11. "github.com/porter-dev/porter/internal/analytics"
  12. "github.com/porter-dev/porter/internal/kubernetes/provisioner"
  13. "github.com/porter-dev/porter/internal/kubernetes/provisioner/aws/ecr"
  14. "github.com/porter-dev/porter/internal/kubernetes/provisioner/aws/eks"
  15. "github.com/porter-dev/porter/internal/kubernetes/provisioner/aws/rds"
  16. "github.com/porter-dev/porter/internal/kubernetes/provisioner/do/docr"
  17. "github.com/porter-dev/porter/internal/kubernetes/provisioner/do/doks"
  18. "github.com/porter-dev/porter/internal/kubernetes/provisioner/gcp/gke"
  19. "github.com/porter-dev/porter/internal/models"
  20. )
  21. type InfraDeleteHandler struct {
  22. handlers.PorterHandlerReadWriter
  23. }
  24. func NewInfraDeleteHandler(
  25. config *config.Config,
  26. decoderValidator shared.RequestDecoderValidator,
  27. writer shared.ResultWriter,
  28. ) *InfraDeleteHandler {
  29. return &InfraDeleteHandler{
  30. PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
  31. }
  32. }
  33. func (c *InfraDeleteHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  34. infra, _ := r.Context().Value(types.InfraScope).(*models.Infra)
  35. if infra.Kind == types.InfraDOKS || infra.Kind == types.InfraGKE || infra.Kind == types.InfraEKS {
  36. c.Config().AnalyticsClient.Track(analytics.ClusterDestroyingStartTrack(
  37. &analytics.ClusterDestroyingStartTrackOpts{
  38. ClusterScopedTrackOpts: analytics.GetClusterScopedTrackOpts(infra.CreatedByUserID, infra.ProjectID, 0),
  39. ClusterType: infra.Kind,
  40. InfraID: infra.ID,
  41. },
  42. ))
  43. }
  44. infra.Status = types.StatusDestroying
  45. infra, err := c.Repo().Infra().UpdateInfra(infra)
  46. if err != nil {
  47. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  48. return
  49. }
  50. switch infra.Kind {
  51. case types.InfraECR:
  52. err = destroyECR(c.Config(), infra)
  53. case types.InfraEKS:
  54. err = destroyEKS(c.Config(), infra)
  55. case types.InfraDOCR:
  56. err = destroyDOCR(c.Config(), infra)
  57. case types.InfraDOKS:
  58. err = destroyDOKS(c.Config(), infra)
  59. case types.InfraGKE:
  60. err = destroyGKE(c.Config(), infra)
  61. case types.InfraRDS:
  62. err = destroyRDS(c.Config(), infra)
  63. }
  64. if err != nil {
  65. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  66. return
  67. }
  68. }
  69. func destroyECR(conf *config.Config, infra *models.Infra) error {
  70. lastAppliedECR := &types.CreateECRInfraRequest{}
  71. // parse infra last applied into ECR config
  72. if err := json.Unmarshal(infra.LastApplied, lastAppliedECR); err != nil {
  73. return err
  74. }
  75. awsInt, err := conf.Repo.AWSIntegration().ReadAWSIntegration(infra.ProjectID, infra.AWSIntegrationID)
  76. if err != nil {
  77. return err
  78. }
  79. opts, err := provision.GetSharedProvisionerOpts(conf, infra)
  80. vaultToken := ""
  81. if conf.CredentialBackend != nil {
  82. vaultToken, err = conf.CredentialBackend.CreateAWSToken(awsInt)
  83. if err != nil {
  84. return err
  85. }
  86. }
  87. opts.CredentialExchange.VaultToken = vaultToken
  88. opts.ECR = &ecr.Conf{
  89. AWSRegion: awsInt.AWSRegion,
  90. ECRName: lastAppliedECR.ECRName,
  91. }
  92. opts.OperationKind = provisioner.Destroy
  93. err = conf.ProvisionerAgent.Provision(opts)
  94. return err
  95. }
  96. func destroyEKS(conf *config.Config, infra *models.Infra) error {
  97. lastAppliedEKS := &types.CreateEKSInfraRequest{}
  98. // parse infra last applied into EKS config
  99. if err := json.Unmarshal(infra.LastApplied, lastAppliedEKS); err != nil {
  100. return err
  101. }
  102. awsInt, err := conf.Repo.AWSIntegration().ReadAWSIntegration(infra.ProjectID, infra.AWSIntegrationID)
  103. if err != nil {
  104. return err
  105. }
  106. opts, err := provision.GetSharedProvisionerOpts(conf, infra)
  107. vaultToken := ""
  108. if conf.CredentialBackend != nil {
  109. vaultToken, err = conf.CredentialBackend.CreateAWSToken(awsInt)
  110. if err != nil {
  111. return err
  112. }
  113. }
  114. opts.CredentialExchange.VaultToken = vaultToken
  115. opts.EKS = &eks.Conf{
  116. AWSRegion: awsInt.AWSRegion,
  117. ClusterName: lastAppliedEKS.EKSName,
  118. MachineType: lastAppliedEKS.MachineType,
  119. IssuerEmail: lastAppliedEKS.IssuerEmail,
  120. }
  121. opts.OperationKind = provisioner.Destroy
  122. err = conf.ProvisionerAgent.Provision(opts)
  123. return err
  124. }
  125. func destroyRDS(conf *config.Config, infra *models.Infra) error {
  126. // find the database and mark as deleting
  127. database, err := conf.Repo.Database().ReadDatabaseByInfraID(infra.ProjectID, infra.ID)
  128. if err != nil {
  129. return err
  130. }
  131. database.Status = "destroying"
  132. database, err = conf.Repo.Database().UpdateDatabase(database)
  133. if err != nil {
  134. return err
  135. }
  136. lastAppliedRDS := &types.RDSInfraLastApplied{}
  137. // parse infra last applied into EKS config
  138. if err := json.Unmarshal(infra.LastApplied, lastAppliedRDS); err != nil {
  139. return err
  140. }
  141. awsInt, err := conf.Repo.AWSIntegration().ReadAWSIntegration(infra.ProjectID, infra.AWSIntegrationID)
  142. if err != nil {
  143. return err
  144. }
  145. opts, err := provision.GetSharedProvisionerOpts(conf, infra)
  146. vaultToken := ""
  147. if conf.CredentialBackend != nil {
  148. vaultToken, err = conf.CredentialBackend.CreateAWSToken(awsInt)
  149. if err != nil {
  150. return err
  151. }
  152. }
  153. opts.CredentialExchange.VaultToken = vaultToken
  154. opts.RDS = &rds.Conf{
  155. AWSRegion: awsInt.AWSRegion,
  156. DBName: lastAppliedRDS.DBName,
  157. MachineType: lastAppliedRDS.MachineType,
  158. DBEngineVersion: lastAppliedRDS.DBEngineVersion,
  159. DBFamily: lastAppliedRDS.DBFamily,
  160. DBMajorEngineVersion: lastAppliedRDS.DBMajorEngineVersion,
  161. DBAllocatedStorage: lastAppliedRDS.DBStorage,
  162. DBMaxAllocatedStorage: lastAppliedRDS.DBMaxStorage,
  163. DBStorageEncrypted: lastAppliedRDS.DBStorageEncrypted,
  164. Username: lastAppliedRDS.Username,
  165. Password: lastAppliedRDS.Password,
  166. VPCID: lastAppliedRDS.VPCID,
  167. Subnet1: lastAppliedRDS.Subnet1,
  168. Subnet2: lastAppliedRDS.Subnet2,
  169. Subnet3: lastAppliedRDS.Subnet3,
  170. DeletionProtection: lastAppliedRDS.DeletionProtection,
  171. }
  172. opts.OperationKind = provisioner.Destroy
  173. err = conf.ProvisionerAgent.Provision(opts)
  174. return err
  175. }
  176. func destroyDOCR(conf *config.Config, infra *models.Infra) error {
  177. lastAppliedDOCR := &types.CreateDOCRInfraRequest{}
  178. // parse infra last applied into DOCR config
  179. if err := json.Unmarshal(infra.LastApplied, lastAppliedDOCR); err != nil {
  180. return err
  181. }
  182. doInt, err := conf.Repo.OAuthIntegration().ReadOAuthIntegration(infra.ProjectID, infra.DOIntegrationID)
  183. if err != nil {
  184. return err
  185. }
  186. opts, err := provision.GetSharedProvisionerOpts(conf, infra)
  187. vaultToken := ""
  188. if conf.CredentialBackend != nil {
  189. vaultToken, err = conf.CredentialBackend.CreateOAuthToken(doInt)
  190. if err != nil {
  191. return err
  192. }
  193. }
  194. opts.CredentialExchange.VaultToken = vaultToken
  195. opts.DOCR = &docr.Conf{
  196. DOCRName: lastAppliedDOCR.DOCRName,
  197. DOCRSubscriptionTier: lastAppliedDOCR.DOCRSubscriptionTier,
  198. }
  199. opts.OperationKind = provisioner.Destroy
  200. err = conf.ProvisionerAgent.Provision(opts)
  201. return err
  202. }
  203. func destroyDOKS(conf *config.Config, infra *models.Infra) error {
  204. lastAppliedDOKS := &types.CreateDOKSInfraRequest{}
  205. // parse infra last applied into DOKS config
  206. if err := json.Unmarshal(infra.LastApplied, lastAppliedDOKS); err != nil {
  207. return err
  208. }
  209. doInt, err := conf.Repo.OAuthIntegration().ReadOAuthIntegration(infra.ProjectID, infra.DOIntegrationID)
  210. if err != nil {
  211. return err
  212. }
  213. opts, err := provision.GetSharedProvisionerOpts(conf, infra)
  214. vaultToken := ""
  215. if conf.CredentialBackend != nil {
  216. vaultToken, err = conf.CredentialBackend.CreateOAuthToken(doInt)
  217. if err != nil {
  218. return err
  219. }
  220. }
  221. opts.CredentialExchange.VaultToken = vaultToken
  222. opts.DOKS = &doks.Conf{
  223. DORegion: lastAppliedDOKS.DORegion,
  224. DOKSClusterName: lastAppliedDOKS.DOKSName,
  225. IssuerEmail: lastAppliedDOKS.IssuerEmail,
  226. }
  227. opts.OperationKind = provisioner.Destroy
  228. err = conf.ProvisionerAgent.Provision(opts)
  229. return err
  230. }
  231. func destroyGKE(conf *config.Config, infra *models.Infra) error {
  232. lastAppliedGKE := &types.CreateGKEInfraRequest{}
  233. // parse infra last applied into DOKS config
  234. if err := json.Unmarshal(infra.LastApplied, lastAppliedGKE); err != nil {
  235. return err
  236. }
  237. gcpInt, err := conf.Repo.GCPIntegration().ReadGCPIntegration(infra.ProjectID, infra.GCPIntegrationID)
  238. if err != nil {
  239. return err
  240. }
  241. opts, err := provision.GetSharedProvisionerOpts(conf, infra)
  242. vaultToken := ""
  243. if conf.CredentialBackend != nil {
  244. vaultToken, err = conf.CredentialBackend.CreateGCPToken(gcpInt)
  245. if err != nil {
  246. return err
  247. }
  248. }
  249. opts.CredentialExchange.VaultToken = vaultToken
  250. opts.GKE = &gke.Conf{
  251. GCPProjectID: gcpInt.GCPProjectID,
  252. GCPRegion: lastAppliedGKE.GCPRegion,
  253. ClusterName: lastAppliedGKE.GKEName,
  254. IssuerEmail: lastAppliedGKE.IssuerEmail,
  255. }
  256. opts.OperationKind = provisioner.Destroy
  257. err = conf.ProvisionerAgent.Provision(opts)
  258. return err
  259. }