list.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. package environment_groups
  2. import (
  3. "net/http"
  4. "strings"
  5. "time"
  6. "github.com/porter-dev/porter/api/server/authz"
  7. "github.com/porter-dev/porter/api/server/handlers"
  8. "github.com/porter-dev/porter/api/server/shared"
  9. "github.com/porter-dev/porter/api/server/shared/apierrors"
  10. "github.com/porter-dev/porter/api/server/shared/config"
  11. "github.com/porter-dev/porter/api/types"
  12. environmentgroups "github.com/porter-dev/porter/internal/kubernetes/environment_groups"
  13. "github.com/porter-dev/porter/internal/models"
  14. "github.com/porter-dev/porter/internal/telemetry"
  15. )
  16. type ListEnvironmentGroupsHandler struct {
  17. handlers.PorterHandlerReadWriter
  18. authz.KubernetesAgentGetter
  19. }
  20. func NewListEnvironmentGroupsHandler(
  21. config *config.Config,
  22. decoderValidator shared.RequestDecoderValidator,
  23. writer shared.ResultWriter,
  24. ) *ListEnvironmentGroupsHandler {
  25. return &ListEnvironmentGroupsHandler{
  26. PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
  27. KubernetesAgentGetter: authz.NewOutOfClusterAgentGetter(config),
  28. }
  29. }
  30. type ListEnvironmentGroupsResponse struct {
  31. EnvironmentGroups []EnvironmentGroupListItem `json:"environment_groups,omitempty"`
  32. }
  33. type EnvironmentGroupListItem struct {
  34. Name string `json:"name"`
  35. LatestVersion int `json:"latest_version"`
  36. Variables map[string]string `json:"variables"`
  37. SecretVariables map[string]string `json:"secret_variables"`
  38. CreatedAtUTC time.Time `json:"created_at"`
  39. LinkedApplications []string `json:"linked_applications,omitempty"`
  40. }
  41. func (c *ListEnvironmentGroupsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
  42. ctx, span := telemetry.NewSpan(r.Context(), "serve-list-env-groups")
  43. defer span.End()
  44. cluster, _ := ctx.Value(types.ClusterScope).(*models.Cluster)
  45. agent, err := c.GetAgent(r, cluster, "")
  46. if err != nil {
  47. err = telemetry.Error(ctx, span, err, "unable to connect to cluster")
  48. c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusServiceUnavailable))
  49. return
  50. }
  51. allEnvGroupVersions, err := environmentgroups.ListEnvironmentGroups(ctx, agent, environmentgroups.WithNamespace(environmentgroups.Namespace_EnvironmentGroups))
  52. if err != nil {
  53. err = telemetry.Error(ctx, span, err, "unable to list all environment groups")
  54. c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
  55. return
  56. }
  57. envGroupSet := make(map[string]struct{})
  58. for _, envGroup := range allEnvGroupVersions {
  59. if envGroup.Name == "" {
  60. continue
  61. }
  62. if _, ok := envGroupSet[envGroup.Name]; !ok {
  63. envGroupSet[envGroup.Name] = struct{}{}
  64. }
  65. }
  66. var envGroups []EnvironmentGroupListItem
  67. for envGroupName := range envGroupSet {
  68. latestVersion, err := environmentgroups.LatestBaseEnvironmentGroup(ctx, agent, envGroupName)
  69. if err != nil {
  70. err = telemetry.Error(ctx, span, err, "unable to get latest environment groups")
  71. c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
  72. return
  73. }
  74. applications, err := environmentgroups.LinkedApplications(ctx, agent, latestVersion.Name)
  75. if err != nil {
  76. err = telemetry.Error(ctx, span, err, "unable to get linked applications")
  77. c.HandleAPIError(w, r, apierrors.NewErrPassThroughToClient(err, http.StatusInternalServerError))
  78. return
  79. }
  80. applicationSetForEnvGroup := make(map[string]struct{})
  81. for _, app := range applications {
  82. if app.Namespace == "" {
  83. continue
  84. }
  85. if _, ok := applicationSetForEnvGroup[app.Namespace]; !ok {
  86. applicationSetForEnvGroup[app.Namespace] = struct{}{}
  87. }
  88. }
  89. var linkedApplications []string
  90. for appNamespace := range applicationSetForEnvGroup {
  91. porterAppName := strings.TrimPrefix(appNamespace, "porter-stack-")
  92. linkedApplications = append(linkedApplications, porterAppName)
  93. }
  94. secrets := make(map[string]string)
  95. for k, v := range latestVersion.SecretVariables {
  96. secrets[k] = string(v)
  97. }
  98. envGroups = append(envGroups, EnvironmentGroupListItem{
  99. Name: latestVersion.Name,
  100. LatestVersion: latestVersion.Version,
  101. Variables: latestVersion.Variables,
  102. SecretVariables: secrets,
  103. CreatedAtUTC: latestVersion.CreatedAtUTC,
  104. LinkedApplications: linkedApplications,
  105. })
  106. }
  107. c.WriteResult(w, r, ListEnvironmentGroupsResponse{EnvironmentGroups: envGroups})
  108. }