| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- package usage
- import (
- "errors"
- "fmt"
- "time"
- "github.com/porter-dev/porter/api/server/authz"
- "github.com/porter-dev/porter/api/server/shared/config"
- "github.com/porter-dev/porter/api/types"
- "github.com/porter-dev/porter/internal/kubernetes"
- "github.com/porter-dev/porter/internal/kubernetes/nodes"
- "github.com/porter-dev/porter/internal/models"
- "gorm.io/gorm"
- )
- // GetUsage gets a project's current usage and usage limit
- func GetUsage(config *config.Config, proj *models.Project) (
- current, limit *types.ProjectUsage,
- resourceUse *models.ProjectUsageCache,
- err error,
- ) {
- limit, err = GetLimit(config, proj)
- if err != nil {
- return nil, nil, nil, err
- }
- // query for the linked cluster counts
- clusters, err := config.Repo.Cluster().ListClustersByProjectID(proj.ID)
- if err != nil {
- return nil, nil, nil, err
- }
- // query for the linked user counts
- roles, err := config.Repo.Project().ListProjectRoles(proj.ID)
- if err != nil {
- return nil, nil, nil, err
- }
- usageCache, err := config.Repo.ProjectUsage().ReadProjectUsageCache(proj.ID)
- isCacheFound := true
- if isCacheFound = !errors.Is(err, gorm.ErrRecordNotFound); err != nil && isCacheFound {
- return nil, nil, nil, err
- }
- // if the usage cache is 24 hours old, was not found, or usage is over limit,
- // re-query for the usage
- if !isCacheFound || usageCache.Is24HrOld() || usageCache.ResourceMemory > limit.ResourceMemory || usageCache.ResourceCPU > limit.ResourceCPU {
- cpu, memory, err := getResourceUsage(config, clusters)
- if err != nil {
- return nil, nil, nil, err
- }
- if !isCacheFound {
- usageCache = &models.ProjectUsageCache{
- ProjectID: proj.ID,
- ResourceCPU: cpu,
- ResourceMemory: memory,
- }
- } else {
- usageCache.ResourceCPU = cpu
- usageCache.ResourceMemory = memory
- }
- isExceeded := usageCache.ResourceCPU > limit.ResourceCPU || usageCache.ResourceMemory > limit.ResourceMemory
- if !usageCache.Exceeded && isExceeded {
- // update the usage cache with a time exceeded
- currTime := time.Now()
- usageCache.ExceededSince = &currTime
- }
- usageCache.Exceeded = isExceeded
- if !isCacheFound {
- usageCache, err = config.Repo.ProjectUsage().CreateProjectUsageCache(usageCache)
- } else {
- usageCache, err = config.Repo.ProjectUsage().UpdateProjectUsageCache(usageCache)
- }
- }
- return &types.ProjectUsage{
- ResourceCPU: usageCache.ResourceCPU,
- ResourceMemory: usageCache.ResourceMemory,
- Clusters: uint(len(clusters)),
- Users: uint(len(roles)),
- }, limit, usageCache, nil
- }
- // gets the total resource usage across all nodes in all clusters
- func getResourceUsage(config *config.Config, clusters []*models.Cluster) (uint, uint, error) {
- // TODO; pass this in?
- var totCPU, totMem uint = 0, 0
- getter := authz.NewOutOfClusterAgentGetter(config)
- for _, cluster := range clusters {
- ooc := getter.GetOutOfClusterConfig(cluster)
- agent, err := kubernetes.GetAgentOutOfClusterConfig(ooc)
- if err != nil {
- return 0, 0, fmt.Errorf("failed to get agent: %s", err.Error())
- }
- totAlloc, err := nodes.GetAllocatableResources(agent.Clientset)
- if err != nil {
- return 0, 0, fmt.Errorf("failed to get alloc: %s", err.Error())
- }
- totCPU += totAlloc.CPU
- totMem += totAlloc.Memory
- }
- return totCPU / 1000, totMem / (1024 * 1024), nil
- }
|