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 }