get.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. package release
  2. import (
  3. "net/http"
  4. semver "github.com/Masterminds/semver/v3"
  5. "github.com/porter-dev/porter/api/server/authz"
  6. "github.com/porter-dev/porter/api/server/handlers"
  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/helm/loader"
  12. "github.com/porter-dev/porter/internal/models"
  13. "github.com/porter-dev/porter/internal/templater/parser"
  14. "gorm.io/gorm"
  15. "helm.sh/helm/v3/pkg/release"
  16. )
  17. type ReleaseGetHandler struct {
  18. handlers.PorterHandlerWriter
  19. authz.KubernetesAgentGetter
  20. }
  21. func NewReleaseGetHandler(
  22. config *config.Config,
  23. writer shared.ResultWriter,
  24. ) *ReleaseGetHandler {
  25. return &ReleaseGetHandler{
  26. PorterHandlerWriter: handlers.NewDefaultPorterHandler(config, nil, writer),
  27. KubernetesAgentGetter: authz.NewOutOfClusterAgentGetter(config),
  28. }
  29. }
  30. func (c *ReleaseGetHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  31. helmRelease, _ := r.Context().Value(types.ReleaseScope).(*release.Release)
  32. res := &types.Release{
  33. Release: helmRelease,
  34. }
  35. // look up the release in the database; if not found, do not populate Porter fields
  36. cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster)
  37. release, err := c.Repo().Release().ReadRelease(cluster.ID, helmRelease.Name, helmRelease.Namespace)
  38. if err == nil {
  39. res.PorterRelease = release.ToReleaseType()
  40. res.ID = release.ID
  41. res.WebhookToken = release.WebhookToken
  42. if release.GitActionConfig != nil {
  43. res.GitActionConfig = release.GitActionConfig.ToGitActionConfigType()
  44. }
  45. } else if err != gorm.ErrRecordNotFound {
  46. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  47. return
  48. } else {
  49. res.PorterRelease = &types.PorterRelease{}
  50. }
  51. // detect if Porter application chart and attempt to get the latest version
  52. // from chart repo
  53. cache := c.Config().URLCache
  54. chartRepoURL, foundFirst := cache.GetURL(helmRelease.Chart.Metadata.Name)
  55. if !foundFirst {
  56. cache.Update()
  57. chartRepoURL, _ = cache.GetURL(helmRelease.Chart.Metadata.Name)
  58. }
  59. if chartRepoURL != "" {
  60. repoIndex, err := loader.LoadRepoIndexPublic(chartRepoURL)
  61. if err == nil {
  62. porterChart := loader.FindPorterChartInIndexList(repoIndex, res.Chart.Metadata.Name)
  63. res.LatestVersion = res.Chart.Metadata.Version
  64. // set latest version to the greater of porterChart.Versions and res.Chart.Metadata.Version
  65. porterChartVersion, porterChartErr := semver.NewVersion(porterChart.Versions[0])
  66. currChartVersion, currChartErr := semver.NewVersion(res.Chart.Metadata.Version)
  67. if currChartErr == nil && porterChartErr == nil && porterChartVersion.GreaterThan(currChartVersion) {
  68. res.LatestVersion = porterChart.Versions[0]
  69. }
  70. }
  71. }
  72. // look for the form using the dynamic client
  73. dynClient, err := c.GetDynamicClient(r, cluster)
  74. if err != nil {
  75. c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
  76. return
  77. }
  78. parserDef := &parser.ClientConfigDefault{
  79. DynamicClient: dynClient,
  80. HelmChart: helmRelease.Chart,
  81. HelmRelease: helmRelease,
  82. }
  83. form, err := parser.GetFormFromRelease(parserDef, helmRelease)
  84. if err != nil {
  85. // TODO: log non-fatal parsing error
  86. } else {
  87. res.Form = form
  88. }
  89. c.WriteResult(w, r, res)
  90. }