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

Commit

Permalink
enhance: factor project default cc into default cc selection
Browse files Browse the repository at this point in the history
Signed-off-by: Nick Hale <[email protected]>
  • Loading branch information
njhale committed Feb 12, 2024
1 parent 4c74e09 commit b582b35
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 95 deletions.
50 changes: 40 additions & 10 deletions pkg/apis/internal.admin.acorn.io/v1/default.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ import (
"fmt"
"sort"

internalv1 "github.com/acorn-io/runtime/pkg/apis/internal.acorn.io/v1"
"github.com/acorn-io/z"
"sigs.k8s.io/controller-runtime/pkg/client"
)

func getCurrentClusterComputeClassDefault(ctx context.Context, c client.Client) (*ClusterComputeClassInstance, error) {
func getCurrentClusterComputeClassDefault(ctx context.Context, c client.Client, projectDefaultComputeClass string) (*ClusterComputeClassInstance, error) {
clusterComputeClasses := ClusterComputeClassInstanceList{}
if err := c.List(ctx, &clusterComputeClasses, &client.ListOptions{}); err != nil {
return nil, err
Expand All @@ -18,23 +20,34 @@ func getCurrentClusterComputeClassDefault(ctx context.Context, c client.Client)
return clusterComputeClasses.Items[i].Name < clusterComputeClasses.Items[j].Name
})

var defaultCCC *ClusterComputeClassInstance
var defaultCCC, projectDefaultCCC *ClusterComputeClassInstance
for _, clusterComputeClass := range clusterComputeClasses.Items {
if clusterComputeClass.Default {
if defaultCCC != nil {
return nil, fmt.Errorf(
"cannot establish defaults because two default computeclasses exist: %v and %v",
defaultCCC.Name, clusterComputeClass.Name)
}
t := clusterComputeClass // Create a new variable that isn't being iterated on to get a pointer
defaultCCC = &t

// Create a new variable that isn't being iterated on to get a pointer
if projectDefaultComputeClass != "" {
defaultCCC = z.Pointer(clusterComputeClass)
}
}

if clusterComputeClass.Name == projectDefaultComputeClass {
projectDefaultCCC = z.Pointer(clusterComputeClass)
}
}

if projectDefaultCCC != nil {
return projectDefaultCCC, nil
}

return defaultCCC, nil
}

func getCurrentProjectComputeClassDefault(ctx context.Context, c client.Client, namespace string) (*ProjectComputeClassInstance, error) {
func getCurrentProjectComputeClassDefault(ctx context.Context, c client.Client, projectDefaultComputeClass, namespace string) (*ProjectComputeClassInstance, error) {
projectComputeClasses := ProjectComputeClassInstanceList{}
if err := c.List(ctx, &projectComputeClasses, &client.ListOptions{Namespace: namespace}); err != nil {
return nil, err
Expand All @@ -44,31 +57,48 @@ func getCurrentProjectComputeClassDefault(ctx context.Context, c client.Client,
return projectComputeClasses.Items[i].Name < projectComputeClasses.Items[j].Name
})

var defaultPCC *ProjectComputeClassInstance
var defaultPCC, projectDefaultPCC *ProjectComputeClassInstance
for _, projectComputeClass := range projectComputeClasses.Items {
if projectComputeClass.Default {
if defaultPCC != nil {
return nil, fmt.Errorf(
"cannot establish defaults because two default computeclasses exist: %v and %v",
defaultPCC.Name, projectComputeClass.Name)
}
t := projectComputeClass // Create a new variable that isn't being iterated on to get a pointer
defaultPCC = &t

// Create a new variable that isn't being iterated on to get a pointer
if projectDefaultComputeClass != "" {
defaultPCC = z.Pointer(projectComputeClass)
}
}

if projectComputeClass.Name == projectDefaultComputeClass {
projectDefaultPCC = z.Pointer(projectComputeClass)
}
}

if projectDefaultPCC != nil {
return projectDefaultPCC, nil
}

return defaultPCC, nil
}

func GetDefaultComputeClass(ctx context.Context, c client.Client, namespace string) (string, error) {
pcc, err := getCurrentProjectComputeClassDefault(ctx, c, namespace)
var project internalv1.ProjectInstance
if err := c.Get(ctx, client.ObjectKey{Name: namespace}, &project); err != nil {
return "", fmt.Errorf("failed to get projectinstance to determine default compute class: %w", err)
}
projectDefault := project.Status.DefaultComputeClass

pcc, err := getCurrentProjectComputeClassDefault(ctx, c, projectDefault, namespace)
if err != nil {
return "", err
} else if pcc != nil {
return pcc.Name, nil
}

ccc, err := getCurrentClusterComputeClassDefault(ctx, c)
ccc, err := getCurrentClusterComputeClassDefault(ctx, c, projectDefault)
if err != nil {
return "", err
} else if ccc != nil {
Expand Down
91 changes: 9 additions & 82 deletions pkg/computeclasses/computeclasses.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"errors"
"fmt"
"math"
"sort"

"github.com/acorn-io/baaah/pkg/router"
apiv1 "github.com/acorn-io/runtime/pkg/apis/api.acorn.io/v1"
Expand Down Expand Up @@ -145,13 +144,12 @@ func GetComputeClassNameForWorkload(workload string, container internalv1.Contai
return cc
}

// GetClassForWorkload determines what ComputeClass should be used for the given appInstance, container and
// workload.
// GetClassForWorkload determines what ComputeClass should be used for the given appInstance, container, and workload.
func GetClassForWorkload(ctx context.Context, c client.Client, computeClasses internalv1.ComputeClassMap, container internalv1.Container, workload, namespace string) (*internaladminv1.ProjectComputeClassInstance, error) {
var err error
ccName := GetComputeClassNameForWorkload(workload, container, computeClasses)
if ccName == "" {
ccName, err = GetDefaultComputeClass(ctx, c, namespace)
var err error
ccName, err = internaladminv1.GetDefaultComputeClass(ctx, c, namespace)
if err != nil {
return nil, err
}
Expand All @@ -171,90 +169,19 @@ func GetAsProjectComputeClassInstance(ctx context.Context, c client.Client, name
return nil, nil
}

projectComputeClass := internaladminv1.ProjectComputeClassInstance{}
err := c.Get(ctx, router.Key(namespace, computeClass), &projectComputeClass)
if err != nil {
var projectComputeClass internaladminv1.ProjectComputeClassInstance
if err := c.Get(ctx, router.Key(namespace, computeClass), &projectComputeClass); err != nil {
if !apierrors.IsNotFound(err) {
return nil, err
}

clusterComputeClass := internaladminv1.ClusterComputeClassInstance{}
err = c.Get(ctx, router.Key("", computeClass), &clusterComputeClass)
if err != nil {
var clusterComputeClass internaladminv1.ClusterComputeClassInstance
if err := c.Get(ctx, router.Key("", computeClass), &clusterComputeClass); err != nil {
return nil, err
}

cc := internaladminv1.ProjectComputeClassInstance(clusterComputeClass)
return &cc, nil
}
return &projectComputeClass, nil
}

func getCurrentClusterComputeClassDefault(ctx context.Context, c client.Client) (*internaladminv1.ClusterComputeClassInstance, error) {
clusterComputeClasses := internaladminv1.ClusterComputeClassInstanceList{}
if err := c.List(ctx, &clusterComputeClasses, &client.ListOptions{}); err != nil {
return nil, err
}

sort.Slice(clusterComputeClasses.Items, func(i, j int) bool {
return clusterComputeClasses.Items[i].Name < clusterComputeClasses.Items[j].Name
})

var defaultCCC *internaladminv1.ClusterComputeClassInstance
for _, clusterComputeClass := range clusterComputeClasses.Items {
if clusterComputeClass.Default {
if defaultCCC != nil {
return nil, fmt.Errorf(
"cannot establish defaults because two default computeclasses exist: %v and %v",
defaultCCC.Name, clusterComputeClass.Name)
}
t := clusterComputeClass // Create a new variable that isn't being iterated on to get a pointer
defaultCCC = &t
}
}

return defaultCCC, nil
}

func getCurrentProjectComputeClassDefault(ctx context.Context, c client.Client, namespace string) (*internaladminv1.ProjectComputeClassInstance, error) {
projectComputeClasses := internaladminv1.ProjectComputeClassInstanceList{}
if err := c.List(ctx, &projectComputeClasses, &client.ListOptions{Namespace: namespace}); err != nil {
return nil, err
}

sort.Slice(projectComputeClasses.Items, func(i, j int) bool {
return projectComputeClasses.Items[i].Name < projectComputeClasses.Items[j].Name
})

var defaultPCC *internaladminv1.ProjectComputeClassInstance
for _, projectComputeClass := range projectComputeClasses.Items {
if projectComputeClass.Default {
if defaultPCC != nil {
return nil, fmt.Errorf(
"cannot establish defaults because two default computeclasses exist: %v and %v",
defaultPCC.Name, projectComputeClass.Name)
}
t := projectComputeClass // Create a new variable that isn't being iterated on to get a pointer
defaultPCC = &t
}
}

return defaultPCC, nil
}

func GetDefaultComputeClass(ctx context.Context, c client.Client, namespace string) (string, error) {
pcc, err := getCurrentProjectComputeClassDefault(ctx, c, namespace)
if err != nil {
return "", err
} else if pcc != nil {
return pcc.Name, nil
projectComputeClass = internaladminv1.ProjectComputeClassInstance(clusterComputeClass)
}

ccc, err := getCurrentClusterComputeClassDefault(ctx, c)
if err != nil {
return "", err
} else if ccc != nil {
return ccc.Name, nil
}
return "", nil
return &projectComputeClass, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ status:
resolvedOfferings:
containers:
"":
class: sample-compute-class
memory: 0
left:
class: sample-compute-class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ status:
resolvedOfferings:
containers:
"":
class: sample-compute-class
memory: 0
left:
class: sample-compute-class
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ status:
resolvedOfferings:
containers:
"":
class: sample-compute-class
memory: 0
left:
class: sample-compute-class
Expand Down
16 changes: 16 additions & 0 deletions pkg/project/handlers.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package project

import (
"fmt"
"time"

"github.com/acorn-io/baaah/pkg/router"
apiv1 "github.com/acorn-io/runtime/pkg/apis/api.acorn.io/v1"
v1 "github.com/acorn-io/runtime/pkg/apis/internal.acorn.io/v1"
"github.com/acorn-io/runtime/pkg/computeclasses"
"github.com/acorn-io/runtime/pkg/labels"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
Expand All @@ -20,9 +22,23 @@ func SetDefaultComputeClass(req router.Request, resp router.Response) error {
project := req.Object.(*v1.ProjectInstance)
if cc := project.Spec.DefaultComputeClass; cc != "" &&
project.Status.DefaultComputeClass != cc {
// The spec has been changed, update the status field to match.
project.Status.DefaultComputeClass = cc
}

// Check if the given compute class exists
if project.Status.DefaultComputeClass != "" {
if _, err := computeclasses.GetAsProjectComputeClassInstance(req.Ctx, req.Client, project.Status.Namespace, project.Status.DefaultComputeClass); err != nil {
if !apierrors.IsNotFound(err) {
return fmt.Errorf("failed to check existence of default compute class on project [%s] status: %w", project.Name, err)
}

// The compute class does not exist, clear the status field.
project.Status.DefaultComputeClass = ""
}
// TODO(njhale): Unset the status field if the project does not support the same regions as the compute class?
}

resp.Objects(req.Object)
return nil
}
Expand Down

0 comments on commit b582b35

Please sign in to comment.