Skip to content
This repository has been archived by the owner on Mar 16, 2024. It is now read-only.

Commit

Permalink
Merge pull request #2454 from tylerslaton/compute-class-quota
Browse files Browse the repository at this point in the history
enhancement: add ComputeClasses and VolumeClasses field to BaseResources
  • Loading branch information
tylerslaton authored Feb 1, 2024
2 parents 3964bbc + d1ddb42 commit c73cd69
Show file tree
Hide file tree
Showing 16 changed files with 1,708 additions and 412 deletions.
87 changes: 48 additions & 39 deletions pkg/apis/internal.admin.acorn.io/v1/baseresources.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package v1

import (
"errors"
"fmt"
"strings"

"k8s.io/apimachinery/pkg/api/resource"
)

// BaseResources defines resources that should be tracked at any scoped. The two main exclusions
Expand All @@ -16,9 +15,10 @@ type BaseResources struct {
Volumes int `json:"volumes"`
Images int `json:"images"`

VolumeStorage resource.Quantity `json:"volumeStorage"`
Memory resource.Quantity `json:"memory"`
CPU resource.Quantity `json:"cpu"`
// ComputeClasses and VolumeClasses are used to track the amount of compute and volume storage per their
// respective classes
ComputeClasses ComputeClassResources `json:"computeClasses"`
VolumeClasses VolumeClassResources `json:"volumeClasses"`
}

// Add will add the BaseResources of another BaseResources struct into the current one.
Expand All @@ -29,9 +29,14 @@ func (current *BaseResources) Add(incoming BaseResources) {
current.Volumes = Add(current.Volumes, incoming.Volumes)
current.Images = Add(current.Images, incoming.Images)

current.VolumeStorage = AddQuantity(current.VolumeStorage, incoming.VolumeStorage)
current.Memory = AddQuantity(current.Memory, incoming.Memory)
current.CPU = AddQuantity(current.CPU, incoming.CPU)
if current.ComputeClasses == nil {
current.ComputeClasses = ComputeClassResources{}
}
if current.VolumeClasses == nil {
current.VolumeClasses = VolumeClassResources{}
}
current.ComputeClasses.Add(incoming.ComputeClasses)
current.VolumeClasses.Add(incoming.VolumeClasses)
}

// Remove will remove the BaseResources of another BaseResources struct from the current one. Calling remove
Expand All @@ -42,13 +47,9 @@ func (current *BaseResources) Remove(incoming BaseResources, all bool) {
current.Jobs = Sub(current.Jobs, incoming.Jobs)
current.Volumes = Sub(current.Volumes, incoming.Volumes)
current.Images = Sub(current.Images, incoming.Images)

current.Memory = SubQuantity(current.Memory, incoming.Memory)
current.CPU = SubQuantity(current.CPU, incoming.CPU)

// Only remove persistent resources if all is true.
current.ComputeClasses.Remove(incoming.ComputeClasses)
if all {
current.VolumeStorage = SubQuantity(current.VolumeStorage, incoming.VolumeStorage)
current.VolumeClasses.Remove(incoming.VolumeClasses)
}
}

Expand All @@ -58,6 +59,7 @@ func (current *BaseResources) Remove(incoming BaseResources, all bool) {
// If the current BaseResources defines unlimited, then it will always fit.
func (current *BaseResources) Fits(incoming BaseResources) error {
var exceededResources []string
var errs []error

// Check if any of the resources are exceeded
for _, r := range []struct {
Expand All @@ -75,43 +77,51 @@ func (current *BaseResources) Fits(incoming BaseResources) error {
}
}

// Check if any of the quantity resources are exceeded
for _, r := range []struct {
resource string
current, incoming resource.Quantity
}{
{"VolumeStorage", current.VolumeStorage, incoming.VolumeStorage},
{"Memory", current.Memory, incoming.Memory},
{"Cpu", current.CPU, incoming.CPU},
} {
if !FitsQuantity(r.current, r.incoming) {
exceededResources = append(exceededResources, r.resource)
}
if len(exceededResources) != 0 {
errs = append(errs, fmt.Errorf("%w: %s", ErrExceededResources, strings.Join(exceededResources, ", ")))
}

// Build an aggregated error message for the exceeded resources
if len(exceededResources) > 0 {
return fmt.Errorf("%w: %s", ErrExceededResources, strings.Join(exceededResources, ", "))
if err := current.ComputeClasses.Fits(incoming.ComputeClasses); err != nil {
errs = append(errs, err)
}

if err := current.VolumeClasses.Fits(incoming.VolumeClasses); err != nil {
errs = append(errs, err)
}

return nil
// Build an aggregated error message for the exceeded resources
return errors.Join(errs...)
}

// ToString will return a string representation of the BaseResources within the struct.
func (current *BaseResources) ToString() string {
return ResourcesToString(
// make sure that an empty string doesn't have a comma
result := CountResourcesToString(
map[string]int{
"Apps": current.Apps,
"Containers": current.Containers,
"Jobs": current.Jobs,
"Volumes": current.Volumes,
"Images": current.Images,
},
map[string]resource.Quantity{
"VolumeStorage": current.VolumeStorage,
"Memory": current.Memory,
"Cpu": current.CPU,
})
)

for _, resource := range []struct {
name string
asString string
}{
{"ComputeClasses", current.ComputeClasses.ToString()},
{"VolumeClasses", current.VolumeClasses.ToString()},
} {
if result != "" && resource.asString != "" {
result += ", "
}
if resource.asString != "" {
result += fmt.Sprintf("%s: %s", resource.name, resource.asString)
}
}

return result
}

// Equals will check if the current BaseResources struct is equal to another. This is useful
Expand All @@ -122,7 +132,6 @@ func (current *BaseResources) Equals(incoming BaseResources) bool {
current.Jobs == incoming.Jobs &&
current.Volumes == incoming.Volumes &&
current.Images == incoming.Images &&
current.VolumeStorage.Cmp(incoming.VolumeStorage) == 0 &&
current.Memory.Cmp(incoming.Memory) == 0 &&
current.CPU.Cmp(incoming.CPU) == 0
current.ComputeClasses.Equals(incoming.ComputeClasses) &&
current.VolumeClasses.Equals(incoming.VolumeClasses)
}
Loading

0 comments on commit c73cd69

Please sign in to comment.