delete_deployment.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. package environment
  2. import (
  3. "context"
  4. "errors"
  5. "fmt"
  6. "net/http"
  7. "strings"
  8. "github.com/google/go-github/v41/github"
  9. "github.com/porter-dev/porter/api/server/authz"
  10. "github.com/porter-dev/porter/api/server/handlers"
  11. "github.com/porter-dev/porter/api/server/handlers/gitinstallation"
  12. "github.com/porter-dev/porter/api/server/shared"
  13. "github.com/porter-dev/porter/api/server/shared/apierrors"
  14. "github.com/porter-dev/porter/api/server/shared/config"
  15. "github.com/porter-dev/porter/api/server/shared/requestutils"
  16. "github.com/porter-dev/porter/api/types"
  17. "github.com/porter-dev/porter/internal/models"
  18. "gorm.io/gorm"
  19. )
  20. type DeleteDeploymentHandler struct {
  21. handlers.PorterHandlerReadWriter
  22. authz.KubernetesAgentGetter
  23. }
  24. func NewDeleteDeploymentHandler(
  25. config *config.Config,
  26. decoderValidator shared.RequestDecoderValidator,
  27. writer shared.ResultWriter,
  28. ) *DeleteDeploymentHandler {
  29. return &DeleteDeploymentHandler{
  30. PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
  31. KubernetesAgentGetter: authz.NewOutOfClusterAgentGetter(config),
  32. }
  33. }
  34. func (c *DeleteDeploymentHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  35. project, _ := r.Context().Value(types.ProjectScope).(*models.Project)
  36. cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster)
  37. envID, reqErr := requestutils.GetURLParamUint(r, "environment_id")
  38. if reqErr != nil {
  39. c.HandleAPIError(w, r, apierrors.NewErrInternal(reqErr))
  40. return
  41. }
  42. // check that the environment belongs to the project and cluster IDs
  43. env, err := c.Repo().Environment().ReadEnvironmentByID(project.ID, cluster.ID, envID)
  44. if err != nil {
  45. if errors.Is(err, gorm.ErrRecordNotFound) {
  46. c.HandleAPIError(w, r, apierrors.NewErrForbidden(fmt.Errorf("environment id not found in cluster and project")))
  47. return
  48. }
  49. c.HandleAPIError(w, r, apierrors.NewErrInternal(reqErr))
  50. return
  51. }
  52. owner, name, ok := gitinstallation.GetOwnerAndNameParams(c, w, r)
  53. if !ok {
  54. return
  55. }
  56. prNumber, reqErr := requestutils.GetURLParamUint(r, "pr_number")
  57. if reqErr != nil {
  58. c.HandleAPIError(w, r, apierrors.NewErrInternal(reqErr))
  59. return
  60. }
  61. // read the deployment
  62. depl, err := c.Repo().Environment().ReadDeploymentByGitDetails(envID, owner, name, prNumber)
  63. if err != nil {
  64. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  65. return
  66. }
  67. // delete corresponding namespace
  68. agent, err := c.GetAgent(r, cluster, "")
  69. if err != nil {
  70. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  71. return
  72. }
  73. // make sure we don't delete default or kube-system by checking for prefix, for now
  74. if strings.Contains(depl.Namespace, "pr-") {
  75. err = agent.DeleteNamespace(depl.Namespace)
  76. if err != nil {
  77. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  78. return
  79. }
  80. }
  81. client, err := getGithubClientFromEnvironment(c.Config(), env)
  82. if err != nil {
  83. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  84. return
  85. }
  86. // Create new deployment status to indicate deployment is ready
  87. state := "inactive"
  88. deploymentStatusRequest := github.DeploymentStatusRequest{
  89. State: &state,
  90. }
  91. _, _, err = client.Repositories.CreateDeploymentStatus(
  92. context.Background(),
  93. env.GitRepoOwner,
  94. env.GitRepoName,
  95. depl.GHDeploymentID,
  96. &deploymentStatusRequest,
  97. )
  98. if err != nil {
  99. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  100. return
  101. }
  102. depl.Status = types.DeploymentStatusInactive
  103. // update the deployment to mark it inactive
  104. depl, err = c.Repo().Environment().UpdateDeployment(depl)
  105. if err != nil {
  106. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  107. return
  108. }
  109. c.WriteResult(w, r, depl.ToDeploymentType())
  110. }