Repository: kubernetes-sigs/kueue
Pull request #127 (2022-03-18 15:15:19)

Introduce the ResourceFlavor API

#### What type of PR is this?

/kind feature

#### What this PR does / why we need it:

This PR only introduces the type and renames an internal struct to avoid confusion. The next PR will change the ClusterQueue API.


#### Which issue(s) this PR fixes:
Part of #59

#### Special notes for your reviewer:



k8s-ci-robot: @ahg-g: The following test **failed**, say `/retest` to rerun all failed tests or `/retest-required` to rerun all mandatory failed tests:

Test name | Commit | Details | Required | Rerun command
--- | --- | --- | --- | ---
pull-kueue-verify-main | e02b319701543bb24f472e6949e057091872f7c9 | [link](https://prow.k8s.io/view/gs/kubernetes-jenkins/pr-logs/pull/kubernetes-sigs_kueue/127/pull-kueue-verify-main/1504839105131843584) | true | `/test pull-kueue-verify-main`

[Full PR test history](https://prow.k8s.io/pr-history?org=kubernetes-sigs&repo=kueue&pr=127). [Your PR dashboard](https://prow.k8s.io/pr?query=is%3Apr%20state%3Aopen%20author%3Aahg-g). Please help us cut down on flakes by [linking to](https://git.k8s.io/community/contributors/devel/sig-testing/flaky-tests.md#filing-issues-for-flaky-tests) an [open issue](https://github.com/kubernetes-sigs/kueue/issues?q=is:issue+is:open) when you hit one in your PR.

<details>

Instructions for interacting with me using PR comments are available [here](https://git.k8s.io/community/contributors/guide/pull-requests.md).  If you have questions or suggestions related to my behavior, please file an issue against the [kubernetes/test-infra](https://github.com/kubernetes/test-infra/issues/new?title=Prow%20issue:) repository. I understand the commands that are listed [here](https://go.k8s.io/bot-commands).
</details>
<!-- test report -->

Patch:
diff --git a/PROJECT b/PROJECT
index 5dbd458ab..dab69c36a 100644
--- a/PROJECT
+++ b/PROJECT
@@ -31,4 +31,12 @@ resources:
   kind: QueuedWorkload
   path: sigs.k8s.io/kueue/api/v1alpha1
   version: v1alpha1
+- api:
+    crdVersion: v1
+    namespaced: true
+  domain: x-k8s.io
+  group: kueue
+  kind: ResourceFlavor
+  path: sigs.k8s.io/kueue/api/v1alpha1
+  version: v1alpha1
 version: "3"
diff --git a/api/v1alpha1/resourceflavor_types.go b/api/v1alpha1/resourceflavor_types.go
new file mode 100644
index 000000000..50ae436d7
--- /dev/null
+++ b/api/v1alpha1/resourceflavor_types.go
@@ -0,0 +1,54 @@
+/*
+Copyright 2022 The Kubernetes Authors.
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+*/
+
+package v1alpha1
+
+import (
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+)
+
+//+kubebuilder:object:root=true
+//+kubebuilder:subresource:status
+
+// ResourceFlavor is the Schema for the resourceflavors API
+type ResourceFlavor struct {
+	metav1.TypeMeta   `json:",inline"`
+	metav1.ObjectMeta `json:"metadata,omitempty"`
+
+	// labels associated with this flavor. They are matched against or
+	// converted to node affinity constraints on the workload’s pods.
+	// For example, cloud.provider.com/accelerator: nvidia-tesla-k80.
+	Labels map[string]string `json:"labels,omitempty"`
+
+	// taints associated with this flavor that workloads must explicitly
+	// “tolerate” to be able to use this flavor.
+	// For example, cloud.provider.com/preemptible="true":NoSchedule
+	Taints []corev1.Taint `json:"taints,omitempty"`
+}
+
+//+kubebuilder:object:root=true
+
+// ResourceFlavorList contains a list of ResourceFlavor
+type ResourceFlavorList struct {
+	metav1.TypeMeta `json:",inline"`
+	metav1.ListMeta `json:"metadata,omitempty"`
+	Items           []ResourceFlavor `json:"items"`
+}
+
+func init() {
+	SchemeBuilder.Register(&ResourceFlavor{}, &ResourceFlavorList{})
+}
diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go
index 3f4c5eb82..666df1dae 100644
--- a/api/v1alpha1/zz_generated.deepcopy.go
+++ b/api/v1alpha1/zz_generated.deepcopy.go
@@ -494,6 +494,77 @@ func (in *Resource) DeepCopy() *Resource {
 	return out
 }
 
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ResourceFlavor) DeepCopyInto(out *ResourceFlavor) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+	if in.Labels != nil {
+		in, out := &in.Labels, &out.Labels
+		*out = make(map[string]string, len(*in))
+		for key, val := range *in {
+			(*out)[key] = val
+		}
+	}
+	if in.Taints != nil {
+		in, out := &in.Taints, &out.Taints
+		*out = make([]corev1.Taint, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceFlavor.
+func (in *ResourceFlavor) DeepCopy() *ResourceFlavor {
+	if in == nil {
+		return nil
+	}
+	out := new(ResourceFlavor)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ResourceFlavor) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *ResourceFlavorList) DeepCopyInto(out *ResourceFlavorList) {
+	*out = *in
+	out.TypeMeta = in.TypeMeta
+	in.ListMeta.DeepCopyInto(&out.ListMeta)
+	if in.Items != nil {
+		in, out := &in.Items, &out.Items
+		*out = make([]ResourceFlavor, len(*in))
+		for i := range *in {
+			(*in)[i].DeepCopyInto(&(*out)[i])
+		}
+	}
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceFlavorList.
+func (in *ResourceFlavorList) DeepCopy() *ResourceFlavorList {
+	if in == nil {
+		return nil
+	}
+	out := new(ResourceFlavorList)
+	in.DeepCopyInto(out)
+	return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *ResourceFlavorList) DeepCopyObject() runtime.Object {
+	if c := in.DeepCopy(); c != nil {
+		return c
+	}
+	return nil
+}
+
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
 func (in *Usage) DeepCopyInto(out *Usage) {
 	*out = *in
diff --git a/config/crd/bases/kueue.x-k8s.io_resourceflavors.yaml b/config/crd/bases/kueue.x-k8s.io_resourceflavors.yaml
new file mode 100644
index 000000000..6cfbe3013
--- /dev/null
+++ b/config/crd/bases/kueue.x-k8s.io_resourceflavors.yaml
@@ -0,0 +1,80 @@
+---
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    controller-gen.kubebuilder.io/version: v0.8.0
+  creationTimestamp: null
+  name: resourceflavors.kueue.x-k8s.io
+spec:
+  group: kueue.x-k8s.io
+  names:
+    kind: ResourceFlavor
+    listKind: ResourceFlavorList
+    plural: resourceflavors
+    singular: resourceflavor
+  scope: Namespaced
+  versions:
+  - name: v1alpha1
+    schema:
+      openAPIV3Schema:
+        description: ResourceFlavor is the Schema for the resourceflavors API
+        properties:
+          apiVersion:
+            description: 'APIVersion defines the versioned schema of this representation
+              of an object. Servers should convert recognized schemas to the latest
+              internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
+            type: string
+          kind:
+            description: 'Kind is a string value representing the REST resource this
+              object represents. Servers may infer this from the endpoint the client
+              submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
+            type: string
+          labels:
+            additionalProperties:
+              type: string
+            description: 'labels associated with this flavor. They are matched against
+              or converted to node affinity constraints on the workload’s pods. For
+              example, cloud.provider.com/accelerator: nvidia-tesla-k80.'
+            type: object
+          metadata:
+            type: object
+          taints:
+            description: taints associated with this flavor that workloads must explicitly
+              “tolerate” to be able to use this flavor. For example, cloud.provider.com/preemptible="true":NoSchedule
+            items:
+              description: The node this Taint is attached to has the "effect" on
+                any pod that does not tolerate the Taint.
+              properties:
+                effect:
+                  description: Required. The effect of the taint on pods that do not
+                    tolerate the taint. Valid effects are NoSchedule, PreferNoSchedule
+                    and NoExecute.
+                  type: string
+                key:
+                  description: Required. The taint key to be applied to a node.
+                  type: string
+                timeAdded:
+                  description: TimeAdded represents the time at which the taint was
+                    added. It is only written for NoExecute taints.
+                  format: date-time
+                  type: string
+                value:
+                  description: The taint value corresponding to the taint key.
+                  type: string
+              required:
+              - effect
+              - key
+              type: object
+            type: array
+        type: object
+    served: true
+    storage: true
+    subresources:
+      status: {}
+status:
+  acceptedNames:
+    kind: ""
+    plural: ""
+  conditions: []
+  storedVersions: []
diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml
index fafa36f01..c460a41c4 100644
--- a/config/crd/kustomization.yaml
+++ b/config/crd/kustomization.yaml
@@ -5,6 +5,7 @@ resources:
 - bases/kueue.x-k8s.io_queues.yaml
 - bases/kueue.x-k8s.io_clusterqueues.yaml
 - bases/kueue.x-k8s.io_queuedworkloads.yaml
+- bases/kueue.x-k8s.io_resourceflavors.yaml
 #+kubebuilder:scaffold:crdkustomizeresource
 
 patchesStrategicMerge:
@@ -13,6 +14,7 @@ patchesStrategicMerge:
 #- patches/webhook_in_queues.yaml
 #- patches/webhook_in_clusterqueues.yaml
 #- patches/webhook_in_queuedworkloads.yaml
+#- patches/webhook_in_resourceflavors.yaml
 #+kubebuilder:scaffold:crdkustomizewebhookpatch
 
 # [CERTMANAGER] To enable cert-manager, uncomment all the sections with [CERTMANAGER] prefix.
@@ -20,6 +22,7 @@ patchesStrategicMerge:
 #- patches/cainjection_in_queues.yaml
 #- patches/cainjection_in_clusterqueues.yaml
 #- patches/cainjection_in_queuedworkloads.yaml
+#- patches/cainjection_in_resourceflavors.yaml
 #+kubebuilder:scaffold:crdkustomizecainjectionpatch
 
 # the following config is for teaching kustomize how to do kustomization for CRDs.
diff --git a/config/crd/patches/cainjection_in_resourceflavors.yaml b/config/crd/patches/cainjection_in_resourceflavors.yaml
new file mode 100644
index 000000000..df4f60a6b
--- /dev/null
+++ b/config/crd/patches/cainjection_in_resourceflavors.yaml
@@ -0,0 +1,7 @@
+# The following patch adds a directive for certmanager to inject CA into the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  annotations:
+    cert-manager.io/inject-ca-from: $(CERTIFICATE_NAMESPACE)/$(CERTIFICATE_NAME)
+  name: resourceflavors.kueue.x-k8s.io
diff --git a/config/crd/patches/webhook_in_resourceflavors.yaml b/config/crd/patches/webhook_in_resourceflavors.yaml
new file mode 100644
index 000000000..7c6c4fc8e
--- /dev/null
+++ b/config/crd/patches/webhook_in_resourceflavors.yaml
@@ -0,0 +1,16 @@
+# The following patch enables a conversion webhook for the CRD
+apiVersion: apiextensions.k8s.io/v1
+kind: CustomResourceDefinition
+metadata:
+  name: resourceflavors.kueue.x-k8s.io
+spec:
+  conversion:
+    strategy: Webhook
+    webhook:
+      clientConfig:
+        service:
+          namespace: system
+          name: webhook-service
+          path: /convert
+      conversionReviewVersions:
+      - v1
diff --git a/config/rbac/resourceflavor_editor_role.yaml b/config/rbac/resourceflavor_editor_role.yaml
new file mode 100644
index 000000000..b5bc80e02
--- /dev/null
+++ b/config/rbac/resourceflavor_editor_role.yaml
@@ -0,0 +1,24 @@
+# permissions for end users to edit resourceflavors.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: resourceflavor-editor-role
+rules:
+- apiGroups:
+  - kueue.x-k8s.io
+  resources:
+  - resourceflavors
+  verbs:
+  - create
+  - delete
+  - get
+  - list
+  - patch
+  - update
+  - watch
+- apiGroups:
+  - kueue.x-k8s.io
+  resources:
+  - resourceflavors/status
+  verbs:
+  - get
diff --git a/config/rbac/resourceflavor_viewer_role.yaml b/config/rbac/resourceflavor_viewer_role.yaml
new file mode 100644
index 000000000..5f45c1916
--- /dev/null
+++ b/config/rbac/resourceflavor_viewer_role.yaml
@@ -0,0 +1,20 @@
+# permissions for end users to view resourceflavors.
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRole
+metadata:
+  name: resourceflavor-viewer-role
+rules:
+- apiGroups:
+  - kueue.x-k8s.io
+  resources:
+  - resourceflavors
+  verbs:
+  - get
+  - list
+  - watch
+- apiGroups:
+  - kueue.x-k8s.io
+  resources:
+  - resourceflavors/status
+  verbs:
+  - get
diff --git a/config/samples/kueue_v1alpha1_resourceflavor.yaml b/config/samples/kueue_v1alpha1_resourceflavor.yaml
new file mode 100644
index 000000000..34f69ee0b
--- /dev/null
+++ b/config/samples/kueue_v1alpha1_resourceflavor.yaml
@@ -0,0 +1,6 @@
+apiVersion: kueue.x-k8s.io/v1alpha1
+kind: ResourceFlavor
+metadata:
+  name: resourceflavor-sample
+spec:
+  # TODO(user): Add fields here
diff --git a/pkg/cache/cache.go b/pkg/cache/cache.go
index 86d01f9cb..dbae0dea1 100644
--- a/pkg/cache/cache.go
+++ b/pkg/cache/cache.go
@@ -81,19 +81,18 @@ func newCohort(name string, size int) *Cohort {
 type ClusterQueue struct {
 	Name                 string
 	Cohort               *Cohort
-	RequestableResources map[corev1.ResourceName][]FlavorInfo
+	RequestableResources map[corev1.ResourceName][]FlavorLimits
 	UsedResources        Resources
 	Workloads            map[string]*workload.Info
+	NamespaceSelector    labels.Selector
 	// The set of key labels from all flavors of a resource.
 	// Those keys define the affinity terms of a workload
 	// that can be matched against the flavors.
 	LabelKeys map[corev1.ResourceName]sets.String
-
-	NamespaceSelector labels.Selector
 }
 
-// FlavorInfo holds processed flavor type.
-type FlavorInfo struct {
+// FlavorLimits holds a processed ClusterQueue flavor quota.
+type FlavorLimits struct {
 	Name       string
 	Guaranteed int64
 	Ceiling    int64
@@ -198,8 +197,8 @@ func (c *Cache) AddClusterQueue(ctx context.Context, cq *kueue.ClusterQueue) err
 	}
 	c.addClusterQueueToCohort(cqImpl, cq.Spec.Cohort)
 	c.clusterQueues[cq.Name] = cqImpl
-	// On controller restart, an add ClusterQueue event may come after
 
+	// On controller restart, an add ClusterQueue event may come after
 	// add workload events, and so here we explicitly list and add existing workloads.
 	var workloads kueue.QueuedWorkloadList
 	if err := c.client.List(ctx, &workloads, client.MatchingFields{workloadClusterQueueKey: cq.Name}); err != nil {
@@ -428,13 +427,13 @@ func (c *Cache) deleteClusterQueueFromCohort(cq *ClusterQueue) {
 	cq.Cohort = nil
 }
 
-func resourcesByName(in []kueue.Resource) map[corev1.ResourceName][]FlavorInfo {
-	out := make(map[corev1.ResourceName][]FlavorInfo, len(in))
+func resourcesByName(in []kueue.Resource) map[corev1.ResourceName][]FlavorLimits {
+	out := make(map[corev1.ResourceName][]FlavorLimits, len(in))
 	for _, r := range in {
-		flavors := make([]FlavorInfo, len(r.Flavors))
+		flavors := make([]FlavorLimits, len(r.Flavors))
 		for i := range flavors {
 			f := &r.Flavors[i]
-			fInfo := FlavorInfo{
+			fInfo := FlavorLimits{
 				Name:       f.Name,
 				Guaranteed: workload.ResourceValue(r.Name, f.Quota.Guaranteed),
 				Ceiling:    workload.ResourceValue(r.Name, f.Quota.Ceiling),
diff --git a/pkg/queue/manager.go b/pkg/queue/manager.go
index 9b9b710ec..e1da2cb52 100644
--- a/pkg/queue/manager.go
+++ b/pkg/queue/manager.go
@@ -67,12 +67,7 @@ func (m *Manager) AddClusterQueue(ctx context.Context, cq *kueue.ClusterQueue) e
 	if _, ok := m.clusterQueues[cq.Name]; ok {
 		return errClusterQueueAlreadyExists
 	}
-
-	cqImpl, err := newClusterQueue(cq)
-	if err != nil {
-		return err
-	}
-
+	cqImpl := newClusterQueue(cq)
 	m.clusterQueues[cq.Name] = cqImpl
 
 	// Iterate through existing queues, as queues corresponding to this cluster
diff --git a/pkg/queue/queue.go b/pkg/queue/queue.go
index 024237434..d4214f63b 100644
--- a/pkg/queue/queue.go
+++ b/pkg/queue/queue.go
@@ -74,24 +74,15 @@ type ClusterQueue struct {
 	heap heapImpl
 }
 
-func newClusterQueue(cq *kueue.ClusterQueue) (*ClusterQueue, error) {
-	var less lessFunc
-
-	switch cq.Spec.QueueingStrategy {
-	case kueue.StrictFIFO:
-		less = strictFIFO
-	default:
-		return nil, fmt.Errorf("invalid QueueingStrategy %q", cq.Spec.QueueingStrategy)
-	}
-
+func newClusterQueue(cq *kueue.ClusterQueue) *ClusterQueue {
 	cqImpl := &ClusterQueue{
 		heap: heapImpl{
-			less:  less,
+			less:  creationFIFO,
 			items: make(map[string]*heapItem),
 		},
 	}
 	cqImpl.update(cq)
-	return cqImpl, nil
+	return cqImpl
 }
 
 func (cq *ClusterQueue) update(apiCQ *kueue.ClusterQueue) {
@@ -149,10 +140,7 @@ func (cq *ClusterQueue) Pop() *workload.Info {
 	return &w
 }
 
-// strictFIFO is the function used by the clusterQueue heap algorithm to sort
-// workloads. It sorts workloads based on their priority.
-// When priorities are equal, it uses workloads.creationTimestamp.
-func strictFIFO(a, b workload.Info) bool {
+func creationFIFO(a, b workload.Info) bool {
 	p1 := utilpriority.Priority(a.Obj)
 	p2 := utilpriority.Priority(b.Obj)
 
diff --git a/pkg/scheduler/scheduler.go b/pkg/scheduler/scheduler.go
index ff027425c..681207bd6 100644
--- a/pkg/scheduler/scheduler.go
+++ b/pkg/scheduler/scheduler.go
@@ -339,7 +339,7 @@ func flavorSelector(spec *corev1.PodSpec, allowedKeys sets.String) nodeaffinity.
 
 // fitsFlavorLimits returns whether a requested resource fits in a specific flavor's quota limits.
 // If it fits, also returns any borrowing required.
-func fitsFlavorLimits(name corev1.ResourceName, val int64, cq *cache.ClusterQueue, flavor *cache.FlavorInfo) (bool, int64) {
+func fitsFlavorLimits(name corev1.ResourceName, val int64, cq *cache.ClusterQueue, flavor *cache.FlavorLimits) (bool, int64) {
 	used := cq.UsedResources[name][flavor.Name]
 	if used+val > flavor.Ceiling {
 		// Past borrowing limit.


Test patch:
diff --git a/pkg/cache/cache_test.go b/pkg/cache/cache_test.go
index 5ebebbe92..70a2f5e64 100644
--- a/pkg/cache/cache_test.go
+++ b/pkg/cache/cache_test.go
@@ -101,7 +101,7 @@ func TestCacheClusterQueueOperations(t *testing.T) {
 			wantClusterQueues: map[string]*ClusterQueue{
 				"a": {
 					Name: "a",
-					RequestableResources: map[corev1.ResourceName][]FlavorInfo{
+					RequestableResources: map[corev1.ResourceName][]FlavorLimits{
 						corev1.ResourceCPU: {{Name: "default", Guaranteed: 10000, Ceiling: 20000,
 							Labels: map[string]string{"cpuType": "default"}}},
 					},
@@ -111,7 +111,7 @@ func TestCacheClusterQueueOperations(t *testing.T) {
 				},
 				"b": {
 					Name: "b",
-					RequestableResources: map[corev1.ResourceName][]FlavorInfo{
+					RequestableResources: map[corev1.ResourceName][]FlavorLimits{
 						corev1.ResourceCPU: {{Name: "default"}},
 					},
 					NamespaceSelector: labels.Nothing(),
@@ -119,13 +119,13 @@ func TestCacheClusterQueueOperations(t *testing.T) {
 				},
 				"c": {
 					Name:                 "c",
-					RequestableResources: map[corev1.ResourceName][]FlavorInfo{},
+					RequestableResources: map[corev1.ResourceName][]FlavorLimits{},
 					NamespaceSelector:    labels.Nothing(),
 					UsedResources:        Resources{},
 				},
 				"d": {
 					Name:                 "d",
-					RequestableResources: map[corev1.ResourceName][]FlavorInfo{},
+					RequestableResources: map[corev1.ResourceName][]FlavorLimits{},
 					NamespaceSelector:    labels.Nothing(),
 					UsedResources:        Resources{},
 				},
@@ -180,7 +180,7 @@ func TestCacheClusterQueueOperations(t *testing.T) {
 			wantClusterQueues: map[string]*ClusterQueue{
 				"a": {
 					Name: "a",
-					RequestableResources: map[corev1.ResourceName][]FlavorInfo{
+					RequestableResources: map[corev1.ResourceName][]FlavorLimits{
 						corev1.ResourceCPU: {{Name: "default", Guaranteed: 5000, Ceiling: 10000,
 							Labels: map[string]string{"cpuType": "default", "region": "central"},
 						}},
@@ -191,19 +191,19 @@ func TestCacheClusterQueueOperations(t *testing.T) {
 				},
 				"b": {
 					Name:                 "b",
-					RequestableResources: map[corev1.ResourceName][]FlavorInfo{},
+					RequestableResources: map[corev1.ResourceName][]FlavorLimits{},
 					NamespaceSelector:    labels.Everything(),
 					UsedResources:        Resources{},
 				},
 				"c": {
 					Name:                 "c",
-					RequestableResources: map[corev1.ResourceName][]FlavorInfo{},
+					RequestableResources: map[corev1.ResourceName][]FlavorLimits{},
 					NamespaceSelector:    labels.Nothing(),
 					UsedResources:        Resources{},
 				},
 				"d": {
 					Name:                 "d",
-					RequestableResources: map[corev1.ResourceName][]FlavorInfo{},
+					RequestableResources: map[corev1.ResourceName][]FlavorLimits{},
 					NamespaceSelector:    labels.Nothing(),
 					UsedResources:        Resources{},
 				},
@@ -227,13 +227,13 @@ func TestCacheClusterQueueOperations(t *testing.T) {
 			wantClusterQueues: map[string]*ClusterQueue{
 				"b": {
 					Name:                 "b",
-					RequestableResources: map[corev1.ResourceName][]FlavorInfo{},
+					RequestableResources: map[corev1.ResourceName][]FlavorLimits{},
 					NamespaceSelector:    labels.Everything(),
 					UsedResources:        Resources{},
 				},
 				"c": {
 					Name:                 "c",
-					RequestableResources: map[corev1.ResourceName][]FlavorInfo{},
+					RequestableResources: map[corev1.ResourceName][]FlavorLimits{},
 					NamespaceSelector:    labels.Nothing(),
 					UsedResources:        Resources{},
 				},
diff --git a/pkg/cache/snapshot_test.go b/pkg/cache/snapshot_test.go
index 3b3d13e86..a2d5955c5 100644
--- a/pkg/cache/snapshot_test.go
+++ b/pkg/cache/snapshot_test.go
@@ -244,7 +244,7 @@ func TestSnapshot(t *testing.T) {
 			"foofoo": {
 				Name:   "foofoo",
 				Cohort: &wantCohorts[0],
-				RequestableResources: map[corev1.ResourceName][]FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]FlavorLimits{
 					corev1.ResourceCPU: {
 						{
 							Name:       "demand",
@@ -273,7 +273,7 @@ func TestSnapshot(t *testing.T) {
 			"foobar": {
 				Name:   "foobar",
 				Cohort: &wantCohorts[0],
-				RequestableResources: map[corev1.ResourceName][]FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]FlavorLimits{
 					corev1.ResourceCPU: {
 						{
 							Name:       "spot",
@@ -303,7 +303,7 @@ func TestSnapshot(t *testing.T) {
 			},
 			"bar": {
 				Name: "bar",
-				RequestableResources: map[corev1.ResourceName][]FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]FlavorLimits{
 					corev1.ResourceCPU: {
 						{
 							Name:       "default",
diff --git a/pkg/queue/queue_test.go b/pkg/queue/queue_test.go
index 6535aa2f1..42186da7f 100644
--- a/pkg/queue/queue_test.go
+++ b/pkg/queue/queue_test.go
@@ -32,14 +32,11 @@ const (
 )
 
 func TestFIFOClusterQueue(t *testing.T) {
-	q, err := newClusterQueue(&kueue.ClusterQueue{
+	q := newClusterQueue(&kueue.ClusterQueue{
 		Spec: kueue.ClusterQueueSpec{
 			QueueingStrategy: kueue.StrictFIFO,
 		},
 	})
-	if err != nil {
-		t.Fatalf("Failed creating ClusterQueue %v", err)
-	}
 	now := metav1.Now()
 	ws := []*kueue.QueuedWorkload{
 		{
@@ -169,14 +166,11 @@ func TestStrictFIFO(t *testing.T) {
 		},
 	} {
 		t.Run(tt.name, func(t *testing.T) {
-			q, err := newClusterQueue(&kueue.ClusterQueue{
+			q := newClusterQueue(&kueue.ClusterQueue{
 				Spec: kueue.ClusterQueueSpec{
 					QueueingStrategy: kueue.StrictFIFO,
 				},
 			})
-			if err != nil {
-				t.Fatalf("Failed creating ClusterQueue %v", err)
-			}
 
 			q.PushOrUpdate(tt.w1)
 			q.PushOrUpdate(tt.w2)
diff --git a/pkg/scheduler/scheduler_test.go b/pkg/scheduler/scheduler_test.go
index 24d228e51..6a4167a9f 100644
--- a/pkg/scheduler/scheduler_test.go
+++ b/pkg/scheduler/scheduler_test.go
@@ -62,7 +62,6 @@ func TestSchedule(t *testing.T) {
 						},
 					},
 				},
-				QueueingStrategy: kueue.StrictFIFO,
 				RequestableResources: []kueue.Resource{
 					{
 						Name: corev1.ResourceCPU,
@@ -92,7 +91,6 @@ func TestSchedule(t *testing.T) {
 						},
 					},
 				},
-				QueueingStrategy: kueue.StrictFIFO,
 				RequestableResources: []kueue.Resource{
 					{
 						Name: corev1.ResourceCPU,
@@ -129,7 +127,6 @@ func TestSchedule(t *testing.T) {
 						},
 					},
 				},
-				QueueingStrategy: kueue.StrictFIFO,
 				RequestableResources: []kueue.Resource{
 					{
 						Name: corev1.ResourceCPU,
@@ -810,7 +807,7 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
 					corev1.ResourceCPU:    defaultFlavorNoBorrowing(1000),
 					corev1.ResourceMemory: defaultFlavorNoBorrowing(2 * utiltesting.Mi),
 				},
@@ -844,8 +841,8 @@ func TestEntryAssignFlavors(t *testing.T) {
 						}},
 					}}},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
-					corev1.ResourceCPU: noBorrowing([]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
+					corev1.ResourceCPU: noBorrowing([]cache.FlavorLimits{
 						{Name: "default", Guaranteed: 4000, Taints: []corev1.Taint{{
 							Key:    "instance",
 							Value:  "spot",
@@ -872,7 +869,7 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
 					corev1.ResourceCPU: defaultFlavorNoBorrowing(4000),
 				},
 				UsedResources: cache.Resources{
@@ -894,12 +891,12 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
-					corev1.ResourceCPU: noBorrowing([]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
+					corev1.ResourceCPU: noBorrowing([]cache.FlavorLimits{
 						{Name: "one", Guaranteed: 2000},
 						{Name: "two", Guaranteed: 4000},
 					}),
-					corev1.ResourceMemory: noBorrowing([]cache.FlavorInfo{
+					corev1.ResourceMemory: noBorrowing([]cache.FlavorLimits{
 						{Name: "one", Guaranteed: utiltesting.Gi},
 						{Name: "two", Guaranteed: 5 * utiltesting.Mi},
 					}),
@@ -925,12 +922,12 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
-					corev1.ResourceCPU: noBorrowing([]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
+					corev1.ResourceCPU: noBorrowing([]cache.FlavorLimits{
 						{Name: "one", Guaranteed: 2000},
 						{Name: "two", Guaranteed: 4000},
 					}),
-					corev1.ResourceMemory: noBorrowing([]cache.FlavorInfo{
+					corev1.ResourceMemory: noBorrowing([]cache.FlavorLimits{
 						{Name: "one", Guaranteed: utiltesting.Gi},
 						{Name: "two", Guaranteed: 5 * utiltesting.Mi},
 					}),
@@ -948,8 +945,8 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
-					corev1.ResourceCPU: noBorrowing([]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
+					corev1.ResourceCPU: noBorrowing([]cache.FlavorLimits{
 						{Name: "one", Guaranteed: 4000, Taints: []corev1.Taint{{
 							Key:    "instance",
 							Value:  "spot",
@@ -1001,8 +998,8 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
-					corev1.ResourceCPU: noBorrowing([]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
+					corev1.ResourceCPU: noBorrowing([]cache.FlavorLimits{
 						{Name: "one", Guaranteed: 4000, Labels: map[string]string{"cpuType": "one"}},
 						{Name: "two", Guaranteed: 4000, Labels: map[string]string{"cpuType": "two"}},
 					}),
@@ -1057,12 +1054,12 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
-					corev1.ResourceCPU: noBorrowing([]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
+					corev1.ResourceCPU: noBorrowing([]cache.FlavorLimits{
 						{Name: "one", Guaranteed: 4000, Labels: map[string]string{"cpuType": "one", "group": "group1"}},
 						{Name: "two", Guaranteed: 4000, Labels: map[string]string{"cpuType": "two"}},
 					}),
-					corev1.ResourceMemory: noBorrowing([]cache.FlavorInfo{
+					corev1.ResourceMemory: noBorrowing([]cache.FlavorLimits{
 						{Name: "one", Guaranteed: utiltesting.Gi, Labels: map[string]string{"memType": "one"}},
 						{Name: "two", Guaranteed: utiltesting.Gi, Labels: map[string]string{"memType": "two"}},
 					}),
@@ -1125,8 +1122,8 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
-					corev1.ResourceCPU: noBorrowing([]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
+					corev1.ResourceCPU: noBorrowing([]cache.FlavorLimits{
 						{Name: "one", Guaranteed: 4000, Labels: map[string]string{"cpuType": "one"}},
 						{Name: "two", Guaranteed: 4000, Labels: map[string]string{"cpuType": "two"}},
 					}),
@@ -1172,8 +1169,8 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
-					corev1.ResourceCPU: noBorrowing([]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
+					corev1.ResourceCPU: noBorrowing([]cache.FlavorLimits{
 						{Name: "one", Guaranteed: 4000, Labels: map[string]string{"cpuType": "one"}},
 						{Name: "two", Guaranteed: 4000, Labels: map[string]string{"cpuType": "two"}},
 					}),
@@ -1200,8 +1197,8 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
-					corev1.ResourceCPU: noBorrowing([]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
+					corev1.ResourceCPU: noBorrowing([]cache.FlavorLimits{
 						{Name: "one", Guaranteed: 4000},
 						{Name: "two", Guaranteed: 10_000},
 					}),
@@ -1237,7 +1234,7 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
 					corev1.ResourceCPU: {
 						{
 							Name:       "default",
@@ -1295,7 +1292,7 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
 					corev1.ResourceCPU: {
 						{
 							Name:       "one",
@@ -1325,7 +1322,7 @@ func TestEntryAssignFlavors(t *testing.T) {
 				},
 			},
 			clusterQueue: cache.ClusterQueue{
-				RequestableResources: map[corev1.ResourceName][]cache.FlavorInfo{
+				RequestableResources: map[corev1.ResourceName][]cache.FlavorLimits{
 					corev1.ResourceCPU: {
 						{
 							Name:       "one",
@@ -1434,11 +1431,11 @@ func TestEntryOrdering(t *testing.T) {
 	}
 }
 
-func defaultFlavorNoBorrowing(guaranteed int64) []cache.FlavorInfo {
-	return noBorrowing([]cache.FlavorInfo{{Name: "default", Guaranteed: guaranteed}})
+func defaultFlavorNoBorrowing(guaranteed int64) []cache.FlavorLimits {
+	return noBorrowing([]cache.FlavorLimits{{Name: "default", Guaranteed: guaranteed}})
 }
 
-func noBorrowing(flavors []cache.FlavorInfo) []cache.FlavorInfo {
+func noBorrowing(flavors []cache.FlavorLimits) []cache.FlavorLimits {
 	for i := range flavors {
 		flavors[i].Ceiling = flavors[i].Guaranteed
 	}
diff --git a/pkg/util/testing/wrappers.go b/pkg/util/testing/wrappers.go
index 18050cb00..430b2ad65 100644
--- a/pkg/util/testing/wrappers.go
+++ b/pkg/util/testing/wrappers.go
@@ -251,7 +251,6 @@ func MakeClusterQueue(name string) *ClusterQueueWrapper {
 		},
 		Spec: kueue.ClusterQueueSpec{
 			NamespaceSelector: &metav1.LabelSelector{},
-			QueueingStrategy:  kueue.StrictFIFO,
 		},
 	}}
 }