create_candidate.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. package cluster
  2. import (
  3. "net/http"
  4. "github.com/porter-dev/porter/api/server/handlers"
  5. "github.com/porter-dev/porter/api/server/shared"
  6. "github.com/porter-dev/porter/api/server/shared/apierrors"
  7. "github.com/porter-dev/porter/api/server/shared/config"
  8. "github.com/porter-dev/porter/api/types"
  9. "github.com/porter-dev/porter/internal/analytics"
  10. "github.com/porter-dev/porter/internal/kubernetes"
  11. "github.com/porter-dev/porter/internal/models"
  12. "github.com/porter-dev/porter/internal/repository"
  13. )
  14. type CreateClusterCandidateHandler struct {
  15. handlers.PorterHandlerReadWriter
  16. }
  17. func NewCreateClusterCandidateHandler(
  18. config *config.Config,
  19. decoderValidator shared.RequestDecoderValidator,
  20. writer shared.ResultWriter,
  21. ) *CreateClusterCandidateHandler {
  22. return &CreateClusterCandidateHandler{
  23. PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
  24. }
  25. }
  26. func (c *CreateClusterCandidateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  27. // read the project from context
  28. proj, _ := r.Context().Value(types.ProjectScope).(*models.Project)
  29. user, _ := r.Context().Value(types.UserScope).(*models.User)
  30. request := &types.CreateClusterCandidateRequest{}
  31. if ok := c.DecodeAndValidate(w, r, request); !ok {
  32. return
  33. }
  34. ccs, err := getClusterCandidateModelsFromRequest(c.Repo(), proj, request, c.Config().ServerConf.IsLocal)
  35. if err != nil {
  36. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  37. return
  38. }
  39. res := make(types.CreateClusterCandidateResponse, 0)
  40. for _, cc := range ccs {
  41. // handle write to the database
  42. cc, err = c.Repo().Cluster().CreateClusterCandidate(cc)
  43. if err != nil {
  44. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  45. return
  46. }
  47. c.Config().AnalyticsClient.Track(analytics.ClusterConnectionStartTrack(
  48. &analytics.ClusterConnectionStartTrackOpts{
  49. ProjectScopedTrackOpts: analytics.GetProjectScopedTrackOpts(user.ID, proj.ID),
  50. ClusterCandidateID: cc.ID,
  51. },
  52. ))
  53. // if the ClusterCandidate does not have any actions to perform, create the Cluster
  54. // automatically
  55. if len(cc.Resolvers) == 0 {
  56. var cluster *models.Cluster
  57. cluster, cc, err = createClusterFromCandidate(c.Repo(), proj, user, cc, &types.ClusterResolverAll{})
  58. if err != nil {
  59. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  60. return
  61. }
  62. c.Config().AnalyticsClient.Track(analytics.ClusterConnectionSuccessTrack(
  63. &analytics.ClusterConnectionSuccessTrackOpts{
  64. ClusterScopedTrackOpts: analytics.GetClusterScopedTrackOpts(user.ID, proj.ID, cluster.ID),
  65. ClusterCandidateID: cc.ID,
  66. },
  67. ))
  68. }
  69. res = append(res, cc.ToClusterCandidateType())
  70. }
  71. c.WriteResult(w, r, res)
  72. }
  73. func getClusterCandidateModelsFromRequest(
  74. repo repository.Repository,
  75. project *models.Project,
  76. request *types.CreateClusterCandidateRequest,
  77. isServerLocal bool,
  78. ) ([]*models.ClusterCandidate, error) {
  79. candidates, err := kubernetes.GetClusterCandidatesFromKubeconfig(
  80. []byte(request.Kubeconfig),
  81. project.ID,
  82. // can only use "local" auth mechanism if the server is running locally
  83. isServerLocal && request.IsLocal,
  84. )
  85. if err != nil {
  86. return nil, err
  87. }
  88. for _, cc := range candidates {
  89. cc.ProjectID = project.ID
  90. }
  91. return candidates, nil
  92. }