release.go 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778
  1. package authz
  2. import (
  3. "context"
  4. "fmt"
  5. "net/http"
  6. "strings"
  7. "github.com/porter-dev/porter/api/server/shared/apierrors"
  8. "github.com/porter-dev/porter/api/server/shared/config"
  9. "github.com/porter-dev/porter/api/server/shared/requestutils"
  10. "github.com/porter-dev/porter/api/types"
  11. "github.com/porter-dev/porter/internal/models"
  12. "helm.sh/helm/v3/pkg/release"
  13. )
  14. type ReleaseScopedFactory struct {
  15. config *config.Config
  16. }
  17. func NewReleaseScopedFactory(
  18. config *config.Config,
  19. ) *ReleaseScopedFactory {
  20. return &ReleaseScopedFactory{config}
  21. }
  22. func (p *ReleaseScopedFactory) Middleware(next http.Handler) http.Handler {
  23. return &ReleaseScopedMiddleware{next, p.config, NewOutOfClusterAgentGetter(p.config)}
  24. }
  25. type ReleaseScopedMiddleware struct {
  26. next http.Handler
  27. config *config.Config
  28. agentGetter KubernetesAgentGetter
  29. }
  30. func (p *ReleaseScopedMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  31. cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster)
  32. helmAgent, err := p.agentGetter.GetHelmAgent(r, cluster, "")
  33. if err != nil {
  34. apierrors.HandleAPIError(p.config.Logger, p.config.Alerter, w, r, apierrors.NewErrInternal(err), true)
  35. return
  36. }
  37. // get the name of the application
  38. reqScopes, _ := r.Context().Value(types.RequestScopeCtxKey).(map[types.PermissionScope]*types.RequestAction)
  39. name := reqScopes[types.ReleaseScope].Resource.Name
  40. // get the version for the application
  41. version, _ := requestutils.GetURLParamUint(r, types.URLParamReleaseVersion)
  42. release, err := helmAgent.GetRelease(name, int(version), false)
  43. if err != nil {
  44. // ugly casing since at the time of this commit Helm doesn't have an errors package.
  45. // so we rely on the Helm error containing "not found"
  46. if strings.Contains(err.Error(), "not found") {
  47. apierrors.HandleAPIError(p.config.Logger, p.config.Alerter, w, r, apierrors.NewErrPassThroughToClient(
  48. fmt.Errorf("release not found"),
  49. http.StatusNotFound,
  50. ), true)
  51. } else {
  52. apierrors.HandleAPIError(p.config.Logger, p.config.Alerter, w, r, apierrors.NewErrInternal(err), true)
  53. }
  54. return
  55. }
  56. ctx := NewReleaseContext(r.Context(), release)
  57. r = r.Clone(ctx)
  58. p.next.ServeHTTP(w, r)
  59. }
  60. func NewReleaseContext(ctx context.Context, helmRelease *release.Release) context.Context {
  61. return context.WithValue(ctx, types.ReleaseScope, helmRelease)
  62. }