Explorar o código

add status filter to main view

Alexander Belanger %!s(int64=4) %!d(string=hai) anos
pai
achega
3eb274f117

+ 1 - 1
api/server/handlers/environment/create_deployment.go

@@ -77,7 +77,7 @@ func (c *CreateDeploymentHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
 	depl, err := c.Repo().Environment().CreateDeployment(&models.Deployment{
 		EnvironmentID:  env.ID,
 		Namespace:      request.Namespace,
-		Status:         "creating",
+		Status:         types.DeploymentStatusCreating,
 		PullRequestID:  request.PullRequestID,
 		GHDeploymentID: ghDeployment.GetID(),
 		RepoOwner:      request.GitHubMetadata.RepoOwner,

+ 1 - 1
api/server/handlers/environment/delete_deployment.go

@@ -111,7 +111,7 @@ func (c *DeleteDeploymentHandler) ServeHTTP(w http.ResponseWriter, r *http.Reque
 		return
 	}
 
-	depl.Status = "inactive"
+	depl.Status = types.DeploymentStatusInactive
 
 	// update the deployment to mark it inactive
 	depl, err = c.Repo().Environment().UpdateDeployment(depl)

+ 1 - 1
api/server/handlers/environment/finalize_deployment.go

@@ -64,7 +64,7 @@ func (c *FinalizeDeploymentHandler) ServeHTTP(w http.ResponseWriter, r *http.Req
 	}
 
 	depl.Subdomain = request.Subdomain
-	depl.Status = "created"
+	depl.Status = types.DeploymentStatusCreated
 
 	// update the deployment
 	depl, err = c.Repo().Environment().UpdateDeployment(depl)

+ 7 - 1
api/server/handlers/environment/list_deployments.go

@@ -35,6 +35,12 @@ func (c *ListDeploymentsHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
 	project, _ := r.Context().Value(types.ProjectScope).(*models.Project)
 	cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster)
 
+	req := &types.ListDeploymentRequest{}
+
+	if ok := c.DecodeAndValidate(w, r, req); !ok {
+		return
+	}
+
 	owner, name, ok := gitinstallation.GetOwnerAndNameParams(c, w, r)
 
 	if !ok {
@@ -55,7 +61,7 @@ func (c *ListDeploymentsHandler) ServeHTTP(w http.ResponseWriter, r *http.Reques
 		return
 	}
 
-	depls, err := c.Repo().Environment().ListDeployments(env.ID)
+	depls, err := c.Repo().Environment().ListDeployments(env.ID, req.Status...)
 
 	if err != nil {
 		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))

+ 7 - 1
api/server/handlers/environment/list_deployments_by_cluster.go

@@ -29,7 +29,13 @@ func (c *ListDeploymentsByClusterHandler) ServeHTTP(w http.ResponseWriter, r *ht
 	project, _ := r.Context().Value(types.ProjectScope).(*models.Project)
 	cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster)
 
-	depls, err := c.Repo().Environment().ListDeploymentsByCluster(project.ID, cluster.ID)
+	req := &types.ListDeploymentRequest{}
+
+	if ok := c.DecodeAndValidate(w, r, req); !ok {
+		return
+	}
+
+	depls, err := c.Repo().Environment().ListDeploymentsByCluster(project.ID, cluster.ID, req.Status...)
 
 	if err != nil {
 		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))

+ 77 - 0
api/server/handlers/environment/update_deployment_status.go

@@ -0,0 +1,77 @@
+package environment
+
+import (
+	"net/http"
+
+	"github.com/porter-dev/porter/api/server/authz"
+	"github.com/porter-dev/porter/api/server/handlers"
+	"github.com/porter-dev/porter/api/server/handlers/gitinstallation"
+	"github.com/porter-dev/porter/api/server/shared"
+	"github.com/porter-dev/porter/api/server/shared/apierrors"
+	"github.com/porter-dev/porter/api/server/shared/config"
+	"github.com/porter-dev/porter/api/types"
+	"github.com/porter-dev/porter/internal/models"
+	"github.com/porter-dev/porter/internal/models/integrations"
+)
+
+type UpdateDeploymentStatusHandler struct {
+	handlers.PorterHandlerReadWriter
+	authz.KubernetesAgentGetter
+}
+
+func NewUpdateDeploymentStatusHandler(
+	config *config.Config,
+	decoderValidator shared.RequestDecoderValidator,
+	writer shared.ResultWriter,
+) *UpdateDeploymentStatusHandler {
+	return &UpdateDeploymentStatusHandler{
+		PorterHandlerReadWriter: handlers.NewDefaultPorterHandler(config, decoderValidator, writer),
+		KubernetesAgentGetter:   authz.NewOutOfClusterAgentGetter(config),
+	}
+}
+
+func (c *UpdateDeploymentStatusHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
+	ga, _ := r.Context().Value(types.GitInstallationScope).(*integrations.GithubAppInstallation)
+	project, _ := r.Context().Value(types.ProjectScope).(*models.Project)
+	cluster, _ := r.Context().Value(types.ClusterScope).(*models.Cluster)
+
+	owner, name, ok := gitinstallation.GetOwnerAndNameParams(c, w, r)
+
+	if !ok {
+		return
+	}
+
+	request := &types.UpdateDeploymentStatusRequest{}
+
+	if ok := c.DecodeAndValidate(w, r, request); !ok {
+		return
+	}
+
+	// read the environment to get the environment id
+	env, err := c.Repo().Environment().ReadEnvironment(project.ID, cluster.ID, uint(ga.InstallationID), owner, name)
+
+	if err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+
+	// read the deployment
+	depl, err := c.Repo().Environment().ReadDeployment(env.ID, request.Namespace)
+
+	if err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+
+	depl.Status = types.DeploymentStatus(request.Status)
+
+	// create the deployment
+	depl, err = c.Repo().Environment().UpdateDeployment(depl)
+
+	if err != nil {
+		c.HandleAPIError(w, r, apierrors.NewErrInternal(err))
+		return
+	}
+
+	c.WriteResult(w, r, depl.ToDeploymentType())
+}

+ 27 - 7
api/types/environment.go

@@ -23,16 +23,25 @@ type GitHubMetadata struct {
 	CommitSHA    string `json:"gh_commit_sha"`
 }
 
+type DeploymentStatus string
+
+const (
+	DeploymentStatusCreated  DeploymentStatus = "created"
+	DeploymentStatusCreating DeploymentStatus = "creating"
+	DeploymentStatusInactive DeploymentStatus = "inactive"
+	DeploymentStatusFailed   DeploymentStatus = "failed"
+)
+
 type Deployment struct {
 	*GitHubMetadata
 
-	ID                uint   `json:"id"`
-	GitInstallationID uint   `json:"git_installation_id"`
-	EnvironmentID     uint   `json:"environment_id"`
-	Namespace         string `json:"namespace"`
-	Status            string `json:"status"`
-	Subdomain         string `json:"subdomain"`
-	PullRequestID     uint   `json:"pull_request_id"`
+	ID                uint             `json:"id"`
+	GitInstallationID uint             `json:"git_installation_id"`
+	EnvironmentID     uint             `json:"environment_id"`
+	Namespace         string           `json:"namespace"`
+	Status            DeploymentStatus `json:"status"`
+	Subdomain         string           `json:"subdomain"`
+	PullRequestID     uint             `json:"pull_request_id"`
 }
 
 type CreateGHDeploymentRequest struct {
@@ -60,6 +69,17 @@ type UpdateDeploymentRequest struct {
 	Namespace string `json:"namespace" form:"required"`
 }
 
+type ListDeploymentRequest struct {
+	Status []string `schema:"status"`
+}
+
+type UpdateDeploymentStatusRequest struct {
+	*CreateGHDeploymentRequest
+
+	Status    string `json:"status" form:"required,oneof=created creating inactive failed"`
+	Namespace string `json:"namespace" form:"required"`
+}
+
 type DeleteDeploymentRequest struct {
 	Namespace string `json:"namespace" form:"required"`
 }

+ 55 - 4
dashboard/src/main/home/cluster-dashboard/dashboard/preview-environments/EnvironmentList.tsx

@@ -5,6 +5,7 @@ import api from "shared/api";
 import { useHistory, useLocation, useRouteMatch } from "react-router";
 import { getQueryParam } from "shared/routing";
 import styled from "styled-components";
+import Selector from "components/Selector";
 
 import ButtonEnablePREnvironments from "./components/ButtonEnablePREnvironments";
 import ConnectNewRepo from "./components/ConnectNewRepo";
@@ -41,6 +42,7 @@ const EnvironmentList = () => {
   const [hasError, setHasError] = useState(false);
   const [environmentList, setEnvironmentList] = useState<Environment[]>([]);
   const [deploymentList, setDeploymentList] = useState<PRDeployment[]>([]);
+  const [statusSelectorVal, setStatusSelectorVal] = useState<string>("active");
 
   const [showConnectRepoFlow, setShowConnectRepoFlow] = useState(false);
   const { currentProject, currentCluster, setCurrentModal } = useContext(
@@ -52,15 +54,26 @@ const EnvironmentList = () => {
   const location = useLocation();
   const history = useHistory();
 
-  const getPRDeploymentList = () =>
-    api.getPRDeploymentList(
+  const getPRDeploymentList = () => {
+    let status: string[] = [];
+
+    if (statusSelectorVal == "active") {
+      status = ["creating", "created", "failed"];
+    } else if (statusSelectorVal == "inactive") {
+      status = ["inactive"];
+    }
+
+    return api.getPRDeploymentList(
       "<token>",
-      {},
+      {
+        status: status,
+      },
       {
         project_id: currentProject.id,
         cluster_id: currentCluster.id,
       }
     );
+  };
 
   useEffect(() => {
     let isSubscribed = true;
@@ -120,7 +133,7 @@ const EnvironmentList = () => {
     return () => {
       isSubscribed = false;
     };
-  }, [currentCluster, currentProject]);
+  }, [currentCluster, currentProject, statusSelectorVal]);
 
   useEffect(() => {
     const action = getQueryParam({ location }, "action");
@@ -204,6 +217,27 @@ const EnvironmentList = () => {
           <RefreshButton color={"#7d7d81"} onClick={handleRefresh}>
             <i className="material-icons">refresh</i>
           </RefreshButton>
+          <StyledStatusSelector>
+            <Selector
+              activeValue={statusSelectorVal}
+              setActiveValue={setStatusSelectorVal}
+              options={[
+                {
+                  value: "active",
+                  label: "Active",
+                },
+                {
+                  value: "inactive",
+                  label: "Inactive",
+                },
+              ]}
+              dropdownLabel="Status"
+              width="150px"
+              dropdownWidth="230px"
+              closeOverlay={true}
+            />
+          </StyledStatusSelector>
+
           <SettingsButton
             onClick={() => {
               setCurrentModal("PreviewEnvSettingsModal", {});
@@ -355,3 +389,20 @@ const EventsGrid = styled.div`
   grid-row-gap: 20px;
   grid-template-columns: 1;
 `;
+
+const Label = styled.div`
+  display: flex;
+  align-items: center;
+  margin-right: 12px;
+
+  > i {
+    margin-right: 8px;
+    font-size: 18px;
+  }
+`;
+
+const StyledStatusSelector = styled.div`
+  display: flex;
+  align-items: center;
+  font-size: 13px;
+`;

+ 3 - 1
dashboard/src/shared/api.tsx

@@ -339,7 +339,9 @@ const updateNotificationConfig = baseApi<
 });
 
 const getPRDeploymentList = baseApi<
-  {},
+  {
+    status?: string[];
+  },
   {
     cluster_id: number;
     project_id: number;

+ 2 - 2
internal/models/environment.go

@@ -34,7 +34,7 @@ type Deployment struct {
 
 	EnvironmentID  uint
 	Namespace      string
-	Status         string
+	Status         types.DeploymentStatus
 	Subdomain      string
 	PullRequestID  uint
 	GHDeploymentID int64
@@ -70,7 +70,7 @@ type DeploymentWithEnvironment struct {
 
 	Environment    *Environment
 	Namespace      string
-	Status         string
+	Status         types.DeploymentStatus
 	Subdomain      string
 	PullRequestID  uint
 	GHDeploymentID int64

+ 2 - 2
internal/repository/environment.go

@@ -11,8 +11,8 @@ type EnvironmentRepository interface {
 	CreateDeployment(deployment *models.Deployment) (*models.Deployment, error)
 	ReadDeployment(environmentID uint, namespace string) (*models.Deployment, error)
 	ReadDeploymentByCluster(projectID, clusterID uint, namespace string) (*models.Deployment, error)
-	ListDeploymentsByCluster(projectID, clusterID uint) ([]*models.Deployment, error)
-	ListDeployments(environmentID uint) ([]*models.Deployment, error)
+	ListDeploymentsByCluster(projectID, clusterID uint, states ...string) ([]*models.Deployment, error)
+	ListDeployments(environmentID uint, states ...string) ([]*models.Deployment, error)
 	UpdateDeployment(deployment *models.Deployment) (*models.Deployment, error)
 	DeleteDeployment(deployment *models.Deployment) (*models.Deployment, error)
 }

+ 37 - 8
internal/repository/gorm/environment.go

@@ -1,6 +1,8 @@
 package gorm
 
 import (
+	"strings"
+
 	"github.com/porter-dev/porter/internal/models"
 	"github.com/porter-dev/porter/internal/repository"
 	"gorm.io/gorm"
@@ -103,24 +105,51 @@ func (repo *EnvironmentRepository) ReadDeploymentByCluster(projectID, clusterID
 	return depl, nil
 }
 
-func (repo *EnvironmentRepository) ListDeploymentsByCluster(projectID, clusterID uint) ([]*models.Deployment, error) {
-	depls := make([]*models.Deployment, 0)
-
-	if err := repo.db.
+func (repo *EnvironmentRepository) ListDeploymentsByCluster(projectID, clusterID uint, states ...string) ([]*models.Deployment, error) {
+	query := repo.db.
 		Order("deployments.id asc").
 		Joins("INNER JOIN environments ON environments.id = deployments.environment_id").
-		Where("environments.project_id = ? AND environments.cluster_id = ? AND environments.deleted_at IS NULL", projectID, clusterID).
-		Find(&depls).Error; err != nil {
+		Where("environments.project_id = ? AND environments.cluster_id = ? AND environments.deleted_at IS NULL", projectID, clusterID)
+
+	if len(states) > 0 {
+		queryArr := make([]string, len(states))
+		stateInterArr := make([]interface{}, len(states))
+
+		for i, state := range states {
+			queryArr[i] = "deployments.status = ?"
+			stateInterArr[i] = state
+		}
+
+		query = query.Where(strings.Join(queryArr, " OR "), stateInterArr...)
+	}
+
+	depls := make([]*models.Deployment, 0)
+
+	if err := query.Find(&depls).Error; err != nil {
 		return nil, err
 	}
 
 	return depls, nil
 }
 
-func (repo *EnvironmentRepository) ListDeployments(environmentID uint) ([]*models.Deployment, error) {
+func (repo *EnvironmentRepository) ListDeployments(environmentID uint, states ...string) ([]*models.Deployment, error) {
+	query := repo.db.Debug().Order("id asc").Where("environment_id = ?", environmentID)
+
+	if len(states) > 0 {
+		queryArr := make([]string, len(states))
+		stateInterArr := make([]interface{}, len(states))
+
+		for i, state := range states {
+			queryArr[i] = "deployments.status = ?"
+			stateInterArr[i] = state
+		}
+
+		query = query.Where(strings.Join(queryArr, " OR "), stateInterArr...)
+	}
+
 	depls := make([]*models.Deployment, 0)
 
-	if err := repo.db.Order("id asc").Where("environment_id = ?", environmentID).Find(&depls).Error; err != nil {
+	if err := query.Find(&depls).Error; err != nil {
 		return nil, err
 	}
 

+ 2 - 2
internal/repository/test/environment.go

@@ -51,11 +51,11 @@ func (repo *EnvironmentRepository) ReadDeploymentByCluster(projectID, clusterID
 	panic("unimplemented")
 }
 
-func (repo *EnvironmentRepository) ListDeploymentsByCluster(projectID, clusterID uint) ([]*models.Deployment, error) {
+func (repo *EnvironmentRepository) ListDeploymentsByCluster(projectID, clusterID uint, states ...string) ([]*models.Deployment, error) {
 	panic("unimplemented")
 }
 
-func (repo *EnvironmentRepository) ListDeployments(environmentID uint) ([]*models.Deployment, error) {
+func (repo *EnvironmentRepository) ListDeployments(environmentID uint, states ...string) ([]*models.Deployment, error) {
 	panic("unimplemented")
 }