Parcourir la source

Merge branch 'master' of github.com:porter-dev/porter into nico/new-onboarding-flow

jnfrati il y a 4 ans
Parent
commit
8e7f5888e2

+ 2 - 1
api/server/handlers/cluster/create_candidate.go

@@ -67,7 +67,8 @@ func (c *CreateClusterCandidateHandler) ServeHTTP(w http.ResponseWriter, r *http
 		// if the ClusterCandidate does not have any actions to perform, create the Cluster
 		// automatically
 		if len(cc.Resolvers) == 0 {
-			cluster, cc, err := createClusterFromCandidate(c.Repo(), proj, user, cc, &types.ClusterResolverAll{})
+			var cluster *models.Cluster
+			cluster, cc, err = createClusterFromCandidate(c.Repo(), proj, user, cc, &types.ClusterResolverAll{})
 
 			if err != nil {
 				c.HandleAPIError(w, r, apierrors.NewErrInternal(err))

+ 2 - 0
api/server/router/cluster.go

@@ -95,6 +95,8 @@ func getClusterRoutes(
 				types.UserScope,
 				types.ProjectScope,
 			},
+			CheckUsage:  true,
+			UsageMetric: types.Clusters,
 		},
 	)
 

+ 3 - 3
dashboard/src/main/home/cluster-dashboard/env-groups/EnvGroupDashboard.tsx

@@ -99,9 +99,9 @@ class EnvGroupDashboard extends Component<PropsType, StateType> {
             currentCluster={this.props.currentCluster}
             namespace={this.state.namespace}
             sortType={this.state.sortType}
-            setExpandedEnvGroup={(envGroup: any) =>
+            setExpandedEnvGroup={(envGroup: any) => {
               this.setState({ expandedEnvGroup: envGroup })
-            }
+            }}
           />
         </>
       );
@@ -112,7 +112,7 @@ class EnvGroupDashboard extends Component<PropsType, StateType> {
     if (this.state.expandedEnvGroup) {
       return (
         <ExpandedEnvGroup
-          namespace={this.state.namespace}
+          namespace={this.state.expandedEnvGroup?.metadata?.namespace || this.state.namespace}
           currentCluster={this.props.currentCluster}
           envGroup={this.state.expandedEnvGroup}
           closeExpanded={() => this.setState({ expandedEnvGroup: null })}

+ 6 - 0
internal/models/usage.go

@@ -51,6 +51,12 @@ type ProjectUsageCache struct {
 	// The memory usage, in bytes
 	ResourceMemory uint
 
+	// The number of clusters
+	Clusters uint
+
+	// The number of users
+	Users uint
+
 	// Whether the user is exceeding usage
 	Exceeded bool
 

+ 46 - 39
internal/usage/usage.go

@@ -32,6 +32,13 @@ func GetUsage(opts *GetUsageOpts) (
 		return nil, nil, nil, err
 	}
 
+	usageCache, err := opts.Repo.ProjectUsage().ReadProjectUsageCache(opts.Project.ID)
+	isCacheFound := true
+
+	if isCacheFound = !errors.Is(err, gorm.ErrRecordNotFound); err != nil && isCacheFound {
+		return nil, nil, nil, err
+	}
+
 	// query for the linked cluster counts
 	clusters, err := opts.Repo.Cluster().ListClustersByProjectID(opts.Project.ID)
 
@@ -54,71 +61,71 @@ func GetUsage(opts *GetUsageOpts) (
 		}
 	}
 
-	usageCache, err := opts.Repo.ProjectUsage().ReadProjectUsageCache(opts.Project.ID)
-	isCacheFound := true
-
-	if isCacheFound = !errors.Is(err, gorm.ErrRecordNotFound); err != nil && isCacheFound {
-		return nil, nil, nil, err
+	if !isCacheFound {
+		usageCache = &models.ProjectUsageCache{
+			ProjectID: opts.Project.ID,
+		}
 	}
 
-	// if the usage cache is 1 hour old, was not found, or usage is over limit,
-	// re-query for the usage
-	if !isCacheFound || usageCache.Is1HrOld() || usageCache.ResourceMemory > limit.ResourceMemory || usageCache.ResourceCPU > limit.ResourceCPU {
+	oldUsageCache := usageCache
+
+	usageCache.Clusters = uint(len(clusters))
+	usageCache.Users = uint(len(countedRoles))
+
+	// if the usage cache is 1 hour old, was not found, usage is currently over limit, or the clusters/users
+	// counts have changed, re-query for the usage
+	if !isCacheFound || usageCache.Is1HrOld() || isUsageExceeded(usageCache, limit) || isUsageChanged(oldUsageCache, usageCache) {
 		cpu, memory, err := getResourceUsage(opts, clusters)
 
 		if err != nil {
 			return nil, nil, nil, err
 		}
 
-		if !isCacheFound {
-			usageCache = &models.ProjectUsageCache{
-				ProjectID:      opts.Project.ID,
-				ResourceCPU:    cpu,
-				ResourceMemory: memory,
-			}
-		} else {
-			usageCache.ResourceCPU = cpu
-			usageCache.ResourceMemory = memory
-		}
+		usageCache.ResourceCPU = cpu
+		usageCache.ResourceMemory = memory
+	}
 
-		isExceeded := isUsageExceeded(usageCache, limit, uint(len(countedRoles)), uint(len(clusters)))
+	isExceeded := isUsageExceeded(usageCache, limit)
 
-		if !usageCache.Exceeded && isExceeded {
-			// update the usage cache with a time exceeded
-			currTime := time.Now()
-			usageCache.ExceededSince = &currTime
-		}
+	if !usageCache.Exceeded && isExceeded {
+		// update the usage cache with a time exceeded
+		currTime := time.Now()
+		usageCache.ExceededSince = &currTime
+	}
 
-		usageCache.Exceeded = isExceeded
+	usageCache.Exceeded = isExceeded
 
-		if !isCacheFound {
-			usageCache, err = opts.Repo.ProjectUsage().CreateProjectUsageCache(usageCache)
-		} else {
-			usageCache, err = opts.Repo.ProjectUsage().UpdateProjectUsageCache(usageCache)
-		}
+	if !isCacheFound {
+		usageCache, err = opts.Repo.ProjectUsage().CreateProjectUsageCache(usageCache)
+	} else if isUsageChanged(oldUsageCache, usageCache) {
+		usageCache, err = opts.Repo.ProjectUsage().UpdateProjectUsageCache(usageCache)
 	}
 
-	// we check whether it's currently exceeded based on the cache every time, since
-	// it's an inexpensive operation and involves no further DB lookups
-	usageCache.Exceeded = isUsageExceeded(usageCache, limit, uint(len(countedRoles)), uint(len(clusters)))
-
 	return &types.ProjectUsage{
 		ResourceCPU:    usageCache.ResourceCPU,
 		ResourceMemory: usageCache.ResourceMemory,
-		Clusters:       uint(len(clusters)),
-		Users:          uint(len(countedRoles)),
+		Clusters:       usageCache.Clusters,
+		Users:          usageCache.Users,
 	}, limit, usageCache, nil
 }
 
-func isUsageExceeded(usageCache *models.ProjectUsageCache, limit *types.ProjectUsage, numUsers, numClusters uint) bool {
+func isUsageExceeded(usageCache *models.ProjectUsageCache, limit *types.ProjectUsage) bool {
 	isCPUExceeded := limit.ResourceCPU != 0 && usageCache.ResourceCPU > limit.ResourceCPU
 	isMemExceeded := limit.ResourceMemory != 0 && usageCache.ResourceMemory > limit.ResourceMemory
-	isUsersExceeded := limit.Users != 0 && numUsers > limit.Users
-	isClustersExceeded := limit.Clusters != 0 && numClusters > limit.Clusters
+	isUsersExceeded := limit.Users != 0 && usageCache.Users > limit.Users
+	isClustersExceeded := limit.Clusters != 0 && usageCache.Clusters > limit.Clusters
 
 	return isCPUExceeded || isMemExceeded || isUsersExceeded || isClustersExceeded
 }
 
+func isUsageChanged(oldUsageCache, currUsageCache *models.ProjectUsageCache) bool {
+	return oldUsageCache.Exceeded != currUsageCache.Exceeded ||
+		oldUsageCache.Clusters != currUsageCache.Clusters ||
+		oldUsageCache.Users != currUsageCache.Users ||
+		oldUsageCache.ResourceCPU != currUsageCache.ResourceCPU ||
+		oldUsageCache.ResourceMemory != currUsageCache.ResourceMemory
+}
+
 // gets the total resource usage across all nodes in all clusters
 func getResourceUsage(opts *GetUsageOpts, clusters []*models.Cluster) (uint, uint, error) {
 	var totCPU, totMem uint = 0, 0