sigs.k8s.io/kueue@v0.6.2/pkg/util/testing/wrappers.go (about)

     1  /*
     2  Copyright 2022 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package testing
    18  
    19  import (
    20  	"fmt"
    21  	"time"
    22  
    23  	corev1 "k8s.io/api/core/v1"
    24  	nodev1 "k8s.io/api/node/v1"
    25  	schedulingv1 "k8s.io/api/scheduling/v1"
    26  	apimeta "k8s.io/apimachinery/pkg/api/meta"
    27  	"k8s.io/apimachinery/pkg/api/resource"
    28  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    29  	"k8s.io/apimachinery/pkg/runtime/schema"
    30  	"k8s.io/apimachinery/pkg/types"
    31  	"k8s.io/utils/ptr"
    32  
    33  	kueuealpha "sigs.k8s.io/kueue/apis/kueue/v1alpha1"
    34  	kueue "sigs.k8s.io/kueue/apis/kueue/v1beta1"
    35  )
    36  
    37  // PriorityClassWrapper wraps a PriorityClass.
    38  type PriorityClassWrapper struct {
    39  	schedulingv1.PriorityClass
    40  }
    41  
    42  // MakePriorityClass creates a wrapper for a PriorityClass.
    43  func MakePriorityClass(name string) *PriorityClassWrapper {
    44  	return &PriorityClassWrapper{schedulingv1.PriorityClass{
    45  		ObjectMeta: metav1.ObjectMeta{
    46  			Name: name,
    47  		}},
    48  	}
    49  }
    50  
    51  // PriorityValue update value of PriorityClass。
    52  func (p *PriorityClassWrapper) PriorityValue(v int32) *PriorityClassWrapper {
    53  	p.Value = v
    54  	return p
    55  }
    56  
    57  // Obj returns the inner PriorityClass.
    58  func (p *PriorityClassWrapper) Obj() *schedulingv1.PriorityClass {
    59  	return &p.PriorityClass
    60  }
    61  
    62  type WorkloadWrapper struct{ kueue.Workload }
    63  
    64  // MakeWorkload creates a wrapper for a Workload with a single
    65  // pod with a single container.
    66  func MakeWorkload(name, ns string) *WorkloadWrapper {
    67  	return &WorkloadWrapper{kueue.Workload{
    68  		ObjectMeta: metav1.ObjectMeta{Name: name, Namespace: ns},
    69  		Spec: kueue.WorkloadSpec{
    70  			PodSets: []kueue.PodSet{
    71  				*MakePodSet("main", 1).Obj(),
    72  			},
    73  		},
    74  	}}
    75  }
    76  
    77  func (w *WorkloadWrapper) Obj() *kueue.Workload {
    78  	return &w.Workload
    79  }
    80  
    81  func (w *WorkloadWrapper) Clone() *WorkloadWrapper {
    82  	return &WorkloadWrapper{Workload: *w.DeepCopy()}
    83  }
    84  
    85  func (w *WorkloadWrapper) UID(uid types.UID) *WorkloadWrapper {
    86  	w.Workload.UID = uid
    87  	return w
    88  }
    89  
    90  func (w *WorkloadWrapper) Finalizers(fin ...string) *WorkloadWrapper {
    91  	w.ObjectMeta.Finalizers = fin
    92  	return w
    93  }
    94  
    95  func (w *WorkloadWrapper) Request(r corev1.ResourceName, q string) *WorkloadWrapper {
    96  	w.Spec.PodSets[0].Template.Spec.Containers[0].Resources.Requests[r] = resource.MustParse(q)
    97  	return w
    98  }
    99  
   100  func (w *WorkloadWrapper) Limit(r corev1.ResourceName, q string) *WorkloadWrapper {
   101  	res := &w.Spec.PodSets[0].Template.Spec.Containers[0].Resources
   102  	if res.Limits == nil {
   103  		res.Limits = corev1.ResourceList{
   104  			r: resource.MustParse(q),
   105  		}
   106  	} else {
   107  		res.Limits[r] = resource.MustParse(q)
   108  	}
   109  	return w
   110  }
   111  
   112  func (w *WorkloadWrapper) Queue(q string) *WorkloadWrapper {
   113  	w.Spec.QueueName = q
   114  	return w
   115  }
   116  
   117  func (w *WorkloadWrapper) Active(a bool) *WorkloadWrapper {
   118  	w.Spec.Active = ptr.To(a)
   119  	return w
   120  }
   121  
   122  // ReserveQuota sets workload admission and adds a "QuotaReserved" status condition
   123  func (w *WorkloadWrapper) ReserveQuota(a *kueue.Admission) *WorkloadWrapper {
   124  	return w.ReserveQuotaAt(a, time.Now())
   125  }
   126  
   127  // ReserveQuotaAt sets workload admission and adds a "QuotaReserved" status condition
   128  func (w *WorkloadWrapper) ReserveQuotaAt(a *kueue.Admission, now time.Time) *WorkloadWrapper {
   129  	w.Status.Admission = a
   130  	w.Status.Conditions = []metav1.Condition{{
   131  		Type:               kueue.WorkloadQuotaReserved,
   132  		Status:             metav1.ConditionTrue,
   133  		LastTransitionTime: metav1.NewTime(now),
   134  		Reason:             "AdmittedByTest",
   135  		Message:            fmt.Sprintf("Admitted by ClusterQueue %s", w.Status.Admission.ClusterQueue),
   136  	}}
   137  	return w
   138  }
   139  
   140  func (w *WorkloadWrapper) Admitted(a bool) *WorkloadWrapper {
   141  	cond := metav1.Condition{
   142  		Type:               kueue.WorkloadAdmitted,
   143  		Status:             metav1.ConditionTrue,
   144  		LastTransitionTime: metav1.Now(),
   145  		Reason:             "ByTest",
   146  		Message:            fmt.Sprintf("Admitted by ClusterQueue %s", w.Status.Admission.ClusterQueue),
   147  	}
   148  	if !a {
   149  		cond.Status = metav1.ConditionFalse
   150  	}
   151  	apimeta.SetStatusCondition(&w.Status.Conditions, cond)
   152  	return w
   153  }
   154  
   155  func (w *WorkloadWrapper) Finished() *WorkloadWrapper {
   156  	cond := metav1.Condition{
   157  		Type:               kueue.WorkloadFinished,
   158  		Status:             metav1.ConditionTrue,
   159  		LastTransitionTime: metav1.Now(),
   160  		Reason:             "ByTest",
   161  		Message:            "Finished by test",
   162  	}
   163  	apimeta.SetStatusCondition(&w.Status.Conditions, cond)
   164  	return w
   165  }
   166  
   167  func (w *WorkloadWrapper) Creation(t time.Time) *WorkloadWrapper {
   168  	w.CreationTimestamp = metav1.NewTime(t)
   169  	return w
   170  }
   171  
   172  func (w *WorkloadWrapper) PriorityClass(priorityClassName string) *WorkloadWrapper {
   173  	w.Spec.PriorityClassName = priorityClassName
   174  	return w
   175  }
   176  
   177  func (w *WorkloadWrapper) RuntimeClass(name string) *WorkloadWrapper {
   178  	for i := range w.Spec.PodSets {
   179  		w.Spec.PodSets[i].Template.Spec.RuntimeClassName = &name
   180  	}
   181  	return w
   182  }
   183  
   184  func (w *WorkloadWrapper) Priority(priority int32) *WorkloadWrapper {
   185  	w.Spec.Priority = &priority
   186  	return w
   187  }
   188  
   189  func (w *WorkloadWrapper) PriorityClassSource(source string) *WorkloadWrapper {
   190  	w.Spec.PriorityClassSource = source
   191  	return w
   192  }
   193  
   194  func (w *WorkloadWrapper) PodSets(podSets ...kueue.PodSet) *WorkloadWrapper {
   195  	w.Spec.PodSets = podSets
   196  	return w
   197  }
   198  
   199  func (w *WorkloadWrapper) Toleration(t corev1.Toleration) *WorkloadWrapper {
   200  	w.Spec.PodSets[0].Template.Spec.Tolerations = append(w.Spec.PodSets[0].Template.Spec.Tolerations, t)
   201  	return w
   202  }
   203  
   204  func (w *WorkloadWrapper) NodeSelector(kv map[string]string) *WorkloadWrapper {
   205  	w.Spec.PodSets[0].Template.Spec.NodeSelector = kv
   206  	return w
   207  }
   208  
   209  func (w *WorkloadWrapper) Condition(condition metav1.Condition) *WorkloadWrapper {
   210  	apimeta.SetStatusCondition(&w.Status.Conditions, condition)
   211  	return w
   212  }
   213  
   214  func (w *WorkloadWrapper) AdmissionCheck(ac kueue.AdmissionCheckState) *WorkloadWrapper {
   215  	w.Status.AdmissionChecks = append(w.Status.AdmissionChecks, ac)
   216  	return w
   217  }
   218  
   219  func (w *WorkloadWrapper) SetOrReplaceCondition(condition metav1.Condition) *WorkloadWrapper {
   220  	existingCondition := apimeta.FindStatusCondition(w.Status.Conditions, condition.Type)
   221  	if existingCondition != nil {
   222  		apimeta.RemoveStatusCondition(&w.Status.Conditions, condition.Type)
   223  	}
   224  	apimeta.SetStatusCondition(&w.Status.Conditions, condition)
   225  	return w
   226  }
   227  
   228  func (w *WorkloadWrapper) ReclaimablePods(rps ...kueue.ReclaimablePod) *WorkloadWrapper {
   229  	w.Status.ReclaimablePods = rps
   230  	return w
   231  }
   232  
   233  func (w *WorkloadWrapper) Labels(l map[string]string) *WorkloadWrapper {
   234  	w.ObjectMeta.Labels = l
   235  	return w
   236  }
   237  
   238  func (w *WorkloadWrapper) Label(k, v string) *WorkloadWrapper {
   239  	if w.ObjectMeta.Labels == nil {
   240  		w.ObjectMeta.Labels = make(map[string]string)
   241  	}
   242  	w.ObjectMeta.Labels[k] = v
   243  	return w
   244  }
   245  
   246  func (w *WorkloadWrapper) AdmissionChecks(checks ...kueue.AdmissionCheckState) *WorkloadWrapper {
   247  	w.Status.AdmissionChecks = checks
   248  	return w
   249  }
   250  
   251  func (w *WorkloadWrapper) ControllerReference(gvk schema.GroupVersionKind, name, uid string) *WorkloadWrapper {
   252  	w.appendOwnerReference(gvk, name, uid, ptr.To(true), ptr.To(true))
   253  	return w
   254  }
   255  
   256  func (w *WorkloadWrapper) OwnerReference(gvk schema.GroupVersionKind, name, uid string) *WorkloadWrapper {
   257  	w.appendOwnerReference(gvk, name, uid, nil, nil)
   258  	return w
   259  }
   260  
   261  func (w *WorkloadWrapper) appendOwnerReference(gvk schema.GroupVersionKind, name, uid string, controller, blockDeletion *bool) *WorkloadWrapper {
   262  	w.OwnerReferences = append(w.OwnerReferences, metav1.OwnerReference{
   263  		APIVersion:         gvk.GroupVersion().String(),
   264  		Kind:               gvk.Kind,
   265  		Name:               name,
   266  		UID:                types.UID(uid),
   267  		Controller:         controller,
   268  		BlockOwnerDeletion: blockDeletion,
   269  	})
   270  	return w
   271  }
   272  
   273  func (w *WorkloadWrapper) Annotations(kv map[string]string) *WorkloadWrapper {
   274  	w.ObjectMeta.Annotations = kv
   275  	return w
   276  }
   277  
   278  // DeletionTimestamp sets a deletion timestamp for the workload.
   279  func (w *WorkloadWrapper) DeletionTimestamp(t time.Time) *WorkloadWrapper {
   280  	w.Workload.DeletionTimestamp = ptr.To(metav1.NewTime(t).Rfc3339Copy())
   281  	return w
   282  }
   283  
   284  func (w *WorkloadWrapper) RequeueState(count *int32, requeueAt *metav1.Time) *WorkloadWrapper {
   285  	if count == nil && requeueAt == nil {
   286  		w.Status.RequeueState = nil
   287  		return w
   288  	}
   289  	if w.Status.RequeueState == nil {
   290  		w.Status.RequeueState = &kueue.RequeueState{}
   291  	}
   292  	if count != nil {
   293  		w.Status.RequeueState.Count = count
   294  	}
   295  	if requeueAt != nil {
   296  		w.Status.RequeueState.RequeueAt = requeueAt
   297  	}
   298  	return w
   299  }
   300  
   301  func (w *WorkloadWrapper) ResourceVersion(v string) *WorkloadWrapper {
   302  	w.SetResourceVersion(v)
   303  	return w
   304  }
   305  
   306  type PodSetWrapper struct{ kueue.PodSet }
   307  
   308  func MakePodSet(name string, count int) *PodSetWrapper {
   309  	return &PodSetWrapper{
   310  		kueue.PodSet{
   311  			Name:  name,
   312  			Count: int32(count),
   313  			Template: corev1.PodTemplateSpec{
   314  				Spec: corev1.PodSpec{
   315  					RestartPolicy: corev1.RestartPolicyNever,
   316  					Containers: []corev1.Container{
   317  						{
   318  							Name: "c",
   319  							Resources: corev1.ResourceRequirements{
   320  								Requests: make(corev1.ResourceList),
   321  							},
   322  						},
   323  					},
   324  				},
   325  			},
   326  		},
   327  	}
   328  }
   329  
   330  func (p *PodSetWrapper) PriorityClass(pc string) *PodSetWrapper {
   331  	p.Template.Spec.PriorityClassName = pc
   332  	return p
   333  }
   334  
   335  func (p *PodSetWrapper) RuntimeClass(name string) *PodSetWrapper {
   336  	p.Template.Spec.RuntimeClassName = &name
   337  	return p
   338  }
   339  
   340  func (p *PodSetWrapper) Obj() *kueue.PodSet {
   341  	return &p.PodSet
   342  }
   343  
   344  func (p *PodSetWrapper) Request(r corev1.ResourceName, q string) *PodSetWrapper {
   345  	p.Template.Spec.Containers[0].Resources.Requests[r] = resource.MustParse(q)
   346  	return p
   347  }
   348  
   349  func (p *PodSetWrapper) Limit(r corev1.ResourceName, q string) *PodSetWrapper {
   350  	if p.Template.Spec.Containers[0].Resources.Limits == nil {
   351  		p.Template.Spec.Containers[0].Resources.Limits = corev1.ResourceList{}
   352  	}
   353  	p.Template.Spec.Containers[0].Resources.Limits[r] = resource.MustParse(q)
   354  	return p
   355  }
   356  
   357  func (p *PodSetWrapper) Image(image string) *PodSetWrapper {
   358  	p.Template.Spec.Containers[0].Image = image
   359  	return p
   360  }
   361  
   362  func (p *PodSetWrapper) SetMinimumCount(mc int32) *PodSetWrapper {
   363  	p.MinCount = &mc
   364  	return p
   365  }
   366  
   367  func (p *PodSetWrapper) Toleration(t corev1.Toleration) *PodSetWrapper {
   368  	p.Template.Spec.Tolerations = append(p.Template.Spec.Tolerations, t)
   369  	return p
   370  }
   371  
   372  func (p *PodSetWrapper) Containers(containers ...corev1.Container) *PodSetWrapper {
   373  	p.Template.Spec.Containers = containers
   374  	return p
   375  }
   376  
   377  func (p *PodSetWrapper) InitContainers(containers ...corev1.Container) *PodSetWrapper {
   378  	p.Template.Spec.InitContainers = containers
   379  	return p
   380  }
   381  
   382  func (p *PodSetWrapper) NodeSelector(kv map[string]string) *PodSetWrapper {
   383  	p.Template.Spec.NodeSelector = kv
   384  	return p
   385  }
   386  
   387  func (p *PodSetWrapper) Labels(kv map[string]string) *PodSetWrapper {
   388  	p.Template.Labels = kv
   389  	return p
   390  }
   391  
   392  func (p *PodSetWrapper) Annotations(kv map[string]string) *PodSetWrapper {
   393  	p.Template.Annotations = kv
   394  	return p
   395  }
   396  
   397  func (p *PodSetWrapper) SchedulingGates(sg ...corev1.PodSchedulingGate) *PodSetWrapper {
   398  	p.Template.Spec.SchedulingGates = sg
   399  	return p
   400  }
   401  
   402  func (p *PodSetWrapper) PodOverHead(resources corev1.ResourceList) *PodSetWrapper {
   403  	p.Template.Spec.Overhead = resources
   404  	return p
   405  }
   406  
   407  // AdmissionWrapper wraps an Admission
   408  type AdmissionWrapper struct{ kueue.Admission }
   409  
   410  func MakeAdmission(cq string, podSetNames ...string) *AdmissionWrapper {
   411  	wrap := &AdmissionWrapper{kueue.Admission{
   412  		ClusterQueue: kueue.ClusterQueueReference(cq),
   413  	}}
   414  
   415  	if len(podSetNames) == 0 {
   416  		wrap.PodSetAssignments = []kueue.PodSetAssignment{
   417  			{
   418  				Name:          kueue.DefaultPodSetName,
   419  				Flavors:       make(map[corev1.ResourceName]kueue.ResourceFlavorReference),
   420  				ResourceUsage: make(corev1.ResourceList),
   421  				Count:         ptr.To[int32](1),
   422  			},
   423  		}
   424  		return wrap
   425  	}
   426  
   427  	var psFlavors []kueue.PodSetAssignment
   428  	for _, name := range podSetNames {
   429  		psFlavors = append(psFlavors, kueue.PodSetAssignment{
   430  			Name:          name,
   431  			Flavors:       make(map[corev1.ResourceName]kueue.ResourceFlavorReference),
   432  			ResourceUsage: make(corev1.ResourceList),
   433  			Count:         ptr.To[int32](1),
   434  		})
   435  	}
   436  	wrap.PodSetAssignments = psFlavors
   437  	return wrap
   438  }
   439  
   440  func (w *AdmissionWrapper) Obj() *kueue.Admission {
   441  	return &w.Admission
   442  }
   443  
   444  func (w *AdmissionWrapper) Assignment(r corev1.ResourceName, f kueue.ResourceFlavorReference, value string) *AdmissionWrapper {
   445  	w.PodSetAssignments[0].Flavors[r] = f
   446  	w.PodSetAssignments[0].ResourceUsage[r] = resource.MustParse(value)
   447  	return w
   448  }
   449  
   450  func (w *AdmissionWrapper) AssignmentPodCount(value int32) *AdmissionWrapper {
   451  	w.PodSetAssignments[0].Count = ptr.To(value)
   452  	return w
   453  }
   454  
   455  func (w *AdmissionWrapper) PodSets(podSets ...kueue.PodSetAssignment) *AdmissionWrapper {
   456  	w.PodSetAssignments = podSets
   457  	return w
   458  }
   459  
   460  // LocalQueueWrapper wraps a Queue.
   461  type LocalQueueWrapper struct{ kueue.LocalQueue }
   462  
   463  // MakeLocalQueue creates a wrapper for a LocalQueue.
   464  func MakeLocalQueue(name, ns string) *LocalQueueWrapper {
   465  	return &LocalQueueWrapper{kueue.LocalQueue{
   466  		ObjectMeta: metav1.ObjectMeta{
   467  			Name:      name,
   468  			Namespace: ns,
   469  		},
   470  	}}
   471  }
   472  
   473  // Obj returns the inner LocalQueue.
   474  func (q *LocalQueueWrapper) Obj() *kueue.LocalQueue {
   475  	return &q.LocalQueue
   476  }
   477  
   478  // ClusterQueue updates the clusterQueue the queue points to.
   479  func (q *LocalQueueWrapper) ClusterQueue(c string) *LocalQueueWrapper {
   480  	q.Spec.ClusterQueue = kueue.ClusterQueueReference(c)
   481  	return q
   482  }
   483  
   484  // PendingWorkloads updates the pendingWorkloads in status.
   485  func (q *LocalQueueWrapper) PendingWorkloads(n int32) *LocalQueueWrapper {
   486  	q.Status.PendingWorkloads = n
   487  	return q
   488  }
   489  
   490  // ClusterQueueWrapper wraps a ClusterQueue.
   491  type ClusterQueueWrapper struct{ kueue.ClusterQueue }
   492  
   493  // MakeClusterQueue creates a wrapper for a ClusterQueue with a
   494  // select-all NamespaceSelector.
   495  func MakeClusterQueue(name string) *ClusterQueueWrapper {
   496  	return &ClusterQueueWrapper{kueue.ClusterQueue{
   497  		ObjectMeta: metav1.ObjectMeta{
   498  			Name: name,
   499  		},
   500  		Spec: kueue.ClusterQueueSpec{
   501  			NamespaceSelector: &metav1.LabelSelector{},
   502  			QueueingStrategy:  kueue.BestEffortFIFO,
   503  			FlavorFungibility: &kueue.FlavorFungibility{
   504  				WhenCanBorrow:  kueue.Borrow,
   505  				WhenCanPreempt: kueue.TryNextFlavor,
   506  			},
   507  		},
   508  	}}
   509  }
   510  
   511  // Obj returns the inner ClusterQueue.
   512  func (c *ClusterQueueWrapper) Obj() *kueue.ClusterQueue {
   513  	return &c.ClusterQueue
   514  }
   515  
   516  // Cohort sets the borrowing cohort.
   517  func (c *ClusterQueueWrapper) Cohort(cohort string) *ClusterQueueWrapper {
   518  	c.Spec.Cohort = cohort
   519  	return c
   520  }
   521  
   522  // ResourceGroup adds a ResourceGroup with flavors.
   523  func (c *ClusterQueueWrapper) ResourceGroup(flavors ...kueue.FlavorQuotas) *ClusterQueueWrapper {
   524  	rg := kueue.ResourceGroup{
   525  		Flavors: flavors,
   526  	}
   527  	if len(flavors) > 0 {
   528  		var resources []corev1.ResourceName
   529  		for _, r := range flavors[0].Resources {
   530  			resources = append(resources, r.Name)
   531  		}
   532  		for i := 1; i < len(flavors); i++ {
   533  			if len(flavors[i].Resources) != len(resources) {
   534  				panic("Must list the same resources in all flavors in a ResourceGroup")
   535  			}
   536  			for j, r := range flavors[i].Resources {
   537  				if r.Name != resources[j] {
   538  					panic("Must list the same resources in all flavors in a ResourceGroup")
   539  				}
   540  			}
   541  		}
   542  		rg.CoveredResources = resources
   543  	}
   544  	c.Spec.ResourceGroups = append(c.Spec.ResourceGroups, rg)
   545  	return c
   546  }
   547  
   548  // AdmissionChecks replaces the queue additional checks
   549  func (c *ClusterQueueWrapper) AdmissionChecks(checks ...string) *ClusterQueueWrapper {
   550  	c.Spec.AdmissionChecks = checks
   551  	return c
   552  }
   553  
   554  // QueueingStrategy sets the queueing strategy in this ClusterQueue.
   555  func (c *ClusterQueueWrapper) QueueingStrategy(strategy kueue.QueueingStrategy) *ClusterQueueWrapper {
   556  	c.Spec.QueueingStrategy = strategy
   557  	return c
   558  }
   559  
   560  // NamespaceSelector sets the namespace selector.
   561  func (c *ClusterQueueWrapper) NamespaceSelector(s *metav1.LabelSelector) *ClusterQueueWrapper {
   562  	c.Spec.NamespaceSelector = s
   563  	return c
   564  }
   565  
   566  // Preemption sets the preeemption policies.
   567  func (c *ClusterQueueWrapper) Preemption(p kueue.ClusterQueuePreemption) *ClusterQueueWrapper {
   568  	c.Spec.Preemption = &p
   569  	return c
   570  }
   571  
   572  // FlavorFungibility sets the flavorFungibility policies.
   573  func (c *ClusterQueueWrapper) FlavorFungibility(p kueue.FlavorFungibility) *ClusterQueueWrapper {
   574  	c.Spec.FlavorFungibility = &p
   575  	return c
   576  }
   577  
   578  func (c *ClusterQueueWrapper) StopPolicy(p kueue.StopPolicy) *ClusterQueueWrapper {
   579  	c.Spec.StopPolicy = &p
   580  	return c
   581  }
   582  
   583  func (c *ClusterQueueWrapper) Condition(conditionType string, status metav1.ConditionStatus, reason, message string) *ClusterQueueWrapper {
   584  	apimeta.SetStatusCondition(&c.Status.Conditions, metav1.Condition{
   585  		Type:    conditionType,
   586  		Status:  status,
   587  		Reason:  reason,
   588  		Message: message,
   589  	})
   590  	return c
   591  }
   592  
   593  // FlavorQuotasWrapper wraps a FlavorQuotas object.
   594  type FlavorQuotasWrapper struct{ kueue.FlavorQuotas }
   595  
   596  // MakeFlavorQuotas creates a wrapper for a resource flavor.
   597  func MakeFlavorQuotas(name string) *FlavorQuotasWrapper {
   598  	return &FlavorQuotasWrapper{kueue.FlavorQuotas{
   599  		Name: kueue.ResourceFlavorReference(name),
   600  	}}
   601  }
   602  
   603  // Obj returns the inner flavor.
   604  func (f *FlavorQuotasWrapper) Obj() *kueue.FlavorQuotas {
   605  	return &f.FlavorQuotas
   606  }
   607  
   608  func (f *FlavorQuotasWrapper) Resource(name corev1.ResourceName, qs ...string) *FlavorQuotasWrapper {
   609  	rq := kueue.ResourceQuota{
   610  		Name: name,
   611  	}
   612  	if len(qs) > 0 {
   613  		rq.NominalQuota = resource.MustParse(qs[0])
   614  	}
   615  	if len(qs) > 1 && len(qs[1]) > 0 {
   616  		rq.BorrowingLimit = ptr.To(resource.MustParse(qs[1]))
   617  	}
   618  	if len(qs) > 2 && len(qs[2]) > 0 {
   619  		rq.LendingLimit = ptr.To(resource.MustParse(qs[2]))
   620  	}
   621  	if len(qs) > 3 {
   622  		panic("Must have at most 3 quantities for nominalQuota, borrowingLimit and lendingLimit")
   623  	}
   624  
   625  	f.Resources = append(f.Resources, rq)
   626  	return f
   627  }
   628  
   629  // ResourceFlavorWrapper wraps a ResourceFlavor.
   630  type ResourceFlavorWrapper struct{ kueue.ResourceFlavor }
   631  
   632  // MakeResourceFlavor creates a wrapper for a ResourceFlavor.
   633  func MakeResourceFlavor(name string) *ResourceFlavorWrapper {
   634  	return &ResourceFlavorWrapper{kueue.ResourceFlavor{
   635  		ObjectMeta: metav1.ObjectMeta{
   636  			Name: name,
   637  		},
   638  		Spec: kueue.ResourceFlavorSpec{
   639  			NodeLabels: make(map[string]string),
   640  		},
   641  	}}
   642  }
   643  
   644  // Obj returns the inner ResourceFlavor.
   645  func (rf *ResourceFlavorWrapper) Obj() *kueue.ResourceFlavor {
   646  	return &rf.ResourceFlavor
   647  }
   648  
   649  // Label add a label kueue and value pair to the ResourceFlavor.
   650  func (rf *ResourceFlavorWrapper) Label(k, v string) *ResourceFlavorWrapper {
   651  	rf.Spec.NodeLabels[k] = v
   652  	return rf
   653  }
   654  
   655  // Taint adds a taint to the ResourceFlavor.
   656  func (rf *ResourceFlavorWrapper) Taint(t corev1.Taint) *ResourceFlavorWrapper {
   657  	rf.Spec.NodeTaints = append(rf.Spec.NodeTaints, t)
   658  	return rf
   659  }
   660  
   661  // Toleration  adds a taint to the ResourceFlavor.
   662  func (rf *ResourceFlavorWrapper) Toleration(t corev1.Toleration) *ResourceFlavorWrapper {
   663  	rf.Spec.Tolerations = append(rf.Spec.Tolerations, t)
   664  	return rf
   665  }
   666  
   667  // RuntimeClassWrapper wraps a RuntimeClass.
   668  type RuntimeClassWrapper struct{ nodev1.RuntimeClass }
   669  
   670  // MakeRuntimeClass creates a wrapper for a Runtime.
   671  func MakeRuntimeClass(name, handler string) *RuntimeClassWrapper {
   672  	return &RuntimeClassWrapper{nodev1.RuntimeClass{
   673  		ObjectMeta: metav1.ObjectMeta{
   674  			Name: name,
   675  		},
   676  		Handler: handler,
   677  	}}
   678  }
   679  
   680  // PodOverhead adds an Overhead to the RuntimeClass.
   681  func (rc *RuntimeClassWrapper) PodOverhead(resources corev1.ResourceList) *RuntimeClassWrapper {
   682  	rc.Overhead = &nodev1.Overhead{
   683  		PodFixed: resources,
   684  	}
   685  	return rc
   686  }
   687  
   688  // Obj returns the inner flavor.
   689  func (rc *RuntimeClassWrapper) Obj() *nodev1.RuntimeClass {
   690  	return &rc.RuntimeClass
   691  }
   692  
   693  type LimitRangeWrapper struct{ corev1.LimitRange }
   694  
   695  func MakeLimitRange(name, namespace string) *LimitRangeWrapper {
   696  	return &LimitRangeWrapper{
   697  		LimitRange: corev1.LimitRange{
   698  			ObjectMeta: metav1.ObjectMeta{
   699  				Name:      name,
   700  				Namespace: namespace,
   701  			},
   702  			Spec: corev1.LimitRangeSpec{
   703  				Limits: []corev1.LimitRangeItem{
   704  					{
   705  						Type:                 corev1.LimitTypeContainer,
   706  						Max:                  corev1.ResourceList{},
   707  						Min:                  corev1.ResourceList{},
   708  						Default:              corev1.ResourceList{},
   709  						DefaultRequest:       corev1.ResourceList{},
   710  						MaxLimitRequestRatio: corev1.ResourceList{},
   711  					},
   712  				},
   713  			},
   714  		},
   715  	}
   716  }
   717  
   718  func (lr *LimitRangeWrapper) WithType(t corev1.LimitType) *LimitRangeWrapper {
   719  	lr.Spec.Limits[0].Type = t
   720  	return lr
   721  }
   722  
   723  func (lr *LimitRangeWrapper) WithValue(member string, t corev1.ResourceName, q string) *LimitRangeWrapper {
   724  	target := lr.Spec.Limits[0].Max
   725  	switch member {
   726  	case "Min":
   727  		target = lr.Spec.Limits[0].Min
   728  	case "DefaultRequest":
   729  		target = lr.Spec.Limits[0].DefaultRequest
   730  	case "Default":
   731  		target = lr.Spec.Limits[0].Default
   732  	case "Max":
   733  	//nothing
   734  	default:
   735  		panic("Unexpected member " + member)
   736  	}
   737  	target[t] = resource.MustParse(q)
   738  	return lr
   739  }
   740  
   741  func (lr *LimitRangeWrapper) Obj() *corev1.LimitRange {
   742  	return &lr.LimitRange
   743  }
   744  
   745  type AdmissionCheckWrapper struct{ kueue.AdmissionCheck }
   746  
   747  func MakeAdmissionCheck(name string) *AdmissionCheckWrapper {
   748  	return &AdmissionCheckWrapper{
   749  		AdmissionCheck: kueue.AdmissionCheck{
   750  			ObjectMeta: metav1.ObjectMeta{
   751  				Name: name,
   752  			},
   753  		},
   754  	}
   755  }
   756  
   757  func (ac *AdmissionCheckWrapper) Active(status metav1.ConditionStatus) *AdmissionCheckWrapper {
   758  	apimeta.SetStatusCondition(&ac.Status.Conditions, metav1.Condition{
   759  		Type:    kueue.AdmissionCheckActive,
   760  		Status:  status,
   761  		Reason:  "ByTest",
   762  		Message: "by test",
   763  	})
   764  	return ac
   765  }
   766  
   767  func (ac *AdmissionCheckWrapper) Condition(cond metav1.Condition) *AdmissionCheckWrapper {
   768  	apimeta.SetStatusCondition(&ac.Status.Conditions, cond)
   769  	return ac
   770  }
   771  
   772  func (ac *AdmissionCheckWrapper) ControllerName(c string) *AdmissionCheckWrapper {
   773  	ac.Spec.ControllerName = c
   774  	return ac
   775  }
   776  
   777  func (ac *AdmissionCheckWrapper) Parameters(apigroup, kind, name string) *AdmissionCheckWrapper {
   778  	ac.Spec.Parameters = &kueue.AdmissionCheckParametersReference{
   779  		APIGroup: apigroup,
   780  		Kind:     kind,
   781  		Name:     name,
   782  	}
   783  	return ac
   784  }
   785  
   786  func (ac *AdmissionCheckWrapper) Obj() *kueue.AdmissionCheck {
   787  	return &ac.AdmissionCheck
   788  }
   789  
   790  // WorkloadPriorityClassWrapper wraps a WorkloadPriorityClass.
   791  type WorkloadPriorityClassWrapper struct {
   792  	kueue.WorkloadPriorityClass
   793  }
   794  
   795  // MakeWorkloadPriorityClass creates a wrapper for a WorkloadPriorityClass.
   796  func MakeWorkloadPriorityClass(name string) *WorkloadPriorityClassWrapper {
   797  	return &WorkloadPriorityClassWrapper{kueue.WorkloadPriorityClass{
   798  		ObjectMeta: metav1.ObjectMeta{
   799  			Name: name,
   800  		}},
   801  	}
   802  }
   803  
   804  // PriorityValue updates value of WorkloadPriorityClass.
   805  func (p *WorkloadPriorityClassWrapper) PriorityValue(v int32) *WorkloadPriorityClassWrapper {
   806  	p.Value = v
   807  	return p
   808  }
   809  
   810  // Obj returns the inner WorkloadPriorityClass.
   811  func (p *WorkloadPriorityClassWrapper) Obj() *kueue.WorkloadPriorityClass {
   812  	return &p.WorkloadPriorityClass
   813  }
   814  
   815  type MultiKueueConfigWrapper struct {
   816  	kueuealpha.MultiKueueConfig
   817  }
   818  
   819  func MakeMultiKueueConfig(name string) *MultiKueueConfigWrapper {
   820  	return &MultiKueueConfigWrapper{
   821  		MultiKueueConfig: kueuealpha.MultiKueueConfig{
   822  			ObjectMeta: metav1.ObjectMeta{
   823  				Name: name,
   824  			},
   825  		},
   826  	}
   827  }
   828  
   829  func (mkc *MultiKueueConfigWrapper) Obj() *kueuealpha.MultiKueueConfig {
   830  	return &mkc.MultiKueueConfig
   831  }
   832  
   833  func (mkc *MultiKueueConfigWrapper) Clusters(clusters ...string) *MultiKueueConfigWrapper {
   834  	mkc.Spec.Clusters = append(mkc.Spec.Clusters, clusters...)
   835  	return mkc
   836  }
   837  
   838  type MultiKueueClusterWrapper struct {
   839  	kueuealpha.MultiKueueCluster
   840  }
   841  
   842  func MakeMultiKueueCluster(name string) *MultiKueueClusterWrapper {
   843  	return &MultiKueueClusterWrapper{
   844  		MultiKueueCluster: kueuealpha.MultiKueueCluster{
   845  			ObjectMeta: metav1.ObjectMeta{
   846  				Name: name,
   847  			},
   848  		},
   849  	}
   850  }
   851  
   852  func (mkc *MultiKueueClusterWrapper) Obj() *kueuealpha.MultiKueueCluster {
   853  	return &mkc.MultiKueueCluster
   854  }
   855  
   856  func (mkc *MultiKueueClusterWrapper) KubeConfig(LocationType kueuealpha.LocationType, location string) *MultiKueueClusterWrapper {
   857  	mkc.Spec.KubeConfig = kueuealpha.KubeConfig{
   858  		Location:     location,
   859  		LocationType: LocationType,
   860  	}
   861  	return mkc
   862  }
   863  
   864  func (mkc *MultiKueueClusterWrapper) Active(state metav1.ConditionStatus, reason, message string) *MultiKueueClusterWrapper {
   865  	cond := metav1.Condition{
   866  		Type:    kueuealpha.MultiKueueClusterActive,
   867  		Status:  state,
   868  		Reason:  reason,
   869  		Message: message,
   870  	}
   871  	apimeta.SetStatusCondition(&mkc.Status.Conditions, cond)
   872  	return mkc
   873  }