destroy.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. package provision
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "net/http"
  6. "github.com/porter-dev/porter/api/server/shared"
  7. "github.com/porter-dev/porter/api/server/shared/apierrors"
  8. "github.com/porter-dev/porter/api/types"
  9. "github.com/porter-dev/porter/internal/models"
  10. "github.com/porter-dev/porter/provisioner/integrations/provisioner"
  11. "github.com/porter-dev/porter/provisioner/server/config"
  12. ptypes "github.com/porter-dev/porter/provisioner/types"
  13. )
  14. type ProvisionDestroyHandler struct {
  15. Config *config.Config
  16. decoderValidator shared.RequestDecoderValidator
  17. resultWriter shared.ResultWriter
  18. }
  19. func NewProvisionDestroyHandler(
  20. config *config.Config,
  21. ) *ProvisionDestroyHandler {
  22. return &ProvisionDestroyHandler{
  23. Config: config,
  24. decoderValidator: shared.NewDefaultRequestDecoderValidator(config.Logger, config.Alerter),
  25. resultWriter: shared.NewDefaultResultWriter(config.Logger, config.Alerter),
  26. }
  27. }
  28. func (c *ProvisionDestroyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  29. // read the project and infra from the attached scope
  30. infra, _ := r.Context().Value(types.InfraScope).(*models.Infra)
  31. req := &ptypes.DeleteBaseRequest{}
  32. if ok := c.decoderValidator.DecodeAndValidate(w, r, req); !ok {
  33. return
  34. }
  35. // get the values from the previous operation to re-use
  36. lastOp, err := c.Config.Repo.Infra().GetLatestOperation(infra)
  37. if err != nil {
  38. apierrors.HandleAPIError(c.Config.Logger, c.Config.Alerter, w, r, apierrors.NewErrInternal(err), true)
  39. return
  40. }
  41. // create a new operation and write it to the database
  42. operationUID, err := models.GetOperationID()
  43. if err != nil {
  44. apierrors.HandleAPIError(c.Config.Logger, c.Config.Alerter, w, r, apierrors.NewErrInternal(err), true)
  45. return
  46. }
  47. operation := &models.Operation{
  48. UID: operationUID,
  49. InfraID: infra.ID,
  50. Type: req.OperationKind,
  51. Status: "starting",
  52. LastApplied: lastOp.LastApplied,
  53. TemplateVersion: "v0.1.0",
  54. }
  55. operation, err = c.Config.Repo.Infra().AddOperation(infra, operation)
  56. if err != nil {
  57. apierrors.HandleAPIError(c.Config.Logger, c.Config.Alerter, w, r, apierrors.NewErrInternal(err), true)
  58. return
  59. }
  60. ceToken, rawToken, err := createCredentialsExchangeToken(c.Config, infra)
  61. if err != nil {
  62. apierrors.HandleAPIError(c.Config.Logger, c.Config.Alerter, w, r, apierrors.NewErrInternal(err), true)
  63. return
  64. }
  65. // marshal the last applied values into a map[string]interface{}
  66. lastApplied := make(map[string]interface{})
  67. err = json.Unmarshal(lastOp.LastApplied, &lastApplied)
  68. if err != nil {
  69. apierrors.HandleAPIError(c.Config.Logger, c.Config.Alerter, w, r, apierrors.NewErrInternal(err), true)
  70. return
  71. }
  72. // spawn a new provisioning process
  73. err = c.Config.Provisioner.Provision(&provisioner.ProvisionOpts{
  74. Infra: infra,
  75. Operation: operation,
  76. OperationKind: provisioner.Destroy,
  77. Kind: string(infra.Kind),
  78. Values: lastApplied,
  79. CredentialExchange: &provisioner.ProvisionCredentialExchange{
  80. CredExchangeEndpoint: fmt.Sprintf(
  81. "%s/api/v1/%s/credentials",
  82. c.Config.ProvisionerConf.ProvisionerCredExchangeURL,
  83. models.GetWorkspaceID(infra, operation),
  84. ),
  85. CredExchangeToken: rawToken,
  86. CredExchangeID: ceToken.ID,
  87. },
  88. })
  89. if err != nil {
  90. apierrors.HandleAPIError(c.Config.Logger, c.Config.Alerter, w, r, apierrors.NewErrInternal(err), true)
  91. return
  92. }
  93. op, err := operation.ToOperationType()
  94. if err != nil {
  95. apierrors.HandleAPIError(c.Config.Logger, c.Config.Alerter, w, r, apierrors.NewErrInternal(err), true)
  96. return
  97. }
  98. infra.Status = types.InfraStatus("deleting")
  99. infra, err = c.Config.Repo.Infra().UpdateInfra(infra)
  100. if err != nil {
  101. apierrors.HandleAPIError(c.Config.Logger, c.Config.Alerter, w, r, apierrors.NewErrInternal(err), true)
  102. return
  103. }
  104. // return the operation response type to the server
  105. c.resultWriter.WriteResult(w, r, op)
  106. }