sigs.k8s.io/kueue@v0.6.2/pkg/util/testingjobs/pod/wrappers.go (about) 1 /* 2 Copyright 2023 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 pod 18 19 import ( 20 "fmt" 21 "strconv" 22 "time" 23 24 corev1 "k8s.io/api/core/v1" 25 "k8s.io/apimachinery/pkg/api/resource" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/runtime/schema" 28 "k8s.io/apimachinery/pkg/types" 29 "k8s.io/utils/ptr" 30 31 "sigs.k8s.io/kueue/pkg/controller/constants" 32 ) 33 34 // PodWrapper wraps a Pod. 35 type PodWrapper struct { 36 corev1.Pod 37 } 38 39 // MakePod creates a wrapper for a pod with a single container. 40 func MakePod(name, ns string) *PodWrapper { 41 return &PodWrapper{corev1.Pod{ 42 ObjectMeta: metav1.ObjectMeta{ 43 Name: name, 44 Namespace: ns, 45 Annotations: make(map[string]string, 1), 46 }, 47 Spec: corev1.PodSpec{ 48 RestartPolicy: corev1.RestartPolicyNever, 49 Containers: []corev1.Container{ 50 { 51 Name: "c", 52 Image: "pause", 53 Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{}}, 54 }, 55 }, 56 SchedulingGates: make([]corev1.PodSchedulingGate, 0), 57 }, 58 }} 59 } 60 61 // Obj returns the inner Pod. 62 func (p *PodWrapper) Obj() *corev1.Pod { 63 return &p.Pod 64 } 65 66 // Group returns multiple pods that form a pod group, based on the original wrapper. 67 func (p *PodWrapper) MakeGroup(count int) []*corev1.Pod { 68 var pods []*corev1.Pod 69 for i := 0; i < count; i++ { 70 pod := p.Clone().Group(p.Pod.Name).GroupTotalCount(strconv.Itoa(count)) 71 pod.Pod.Name += fmt.Sprintf("-%d", i) 72 pods = append(pods, pod.Obj()) 73 } 74 return pods 75 } 76 77 // Clone returns deep copy of the Pod. 78 func (p *PodWrapper) Clone() *PodWrapper { 79 return &PodWrapper{Pod: *p.DeepCopy()} 80 } 81 82 // Queue updates the queue name of the Pod 83 func (p *PodWrapper) Queue(q string) *PodWrapper { 84 return p.Label(constants.QueueLabel, q) 85 } 86 87 // Queue updates the queue name of the Pod 88 func (p *PodWrapper) PriorityClass(pc string) *PodWrapper { 89 p.Spec.PriorityClassName = pc 90 return p 91 } 92 93 // Name updated the name of the pod 94 func (p *PodWrapper) Name(n string) *PodWrapper { 95 p.ObjectMeta.Name = n 96 return p 97 } 98 99 // Group updates the pod.GroupNameLabel of the Pod 100 func (p *PodWrapper) Group(g string) *PodWrapper { 101 return p.Label("kueue.x-k8s.io/pod-group-name", g) 102 } 103 104 // GroupTotalCount updates the pod.GroupTotalCountAnnotation of the Pod 105 func (p *PodWrapper) GroupTotalCount(gtc string) *PodWrapper { 106 return p.Annotation("kueue.x-k8s.io/pod-group-total-count", gtc) 107 } 108 109 // Label sets the label of the Pod 110 func (p *PodWrapper) Label(k, v string) *PodWrapper { 111 if p.Labels == nil { 112 p.Labels = make(map[string]string) 113 } 114 p.Labels[k] = v 115 return p 116 } 117 118 func (p *PodWrapper) Annotation(key, content string) *PodWrapper { 119 p.Annotations[key] = content 120 return p 121 } 122 123 // RoleHash updates the pod.RoleHashAnnotation of the pod 124 func (p *PodWrapper) RoleHash(h string) *PodWrapper { 125 return p.Annotation("kueue.x-k8s.io/role-hash", h) 126 } 127 128 // ParentWorkload sets the parent-workload annotation 129 func (p *PodWrapper) ParentWorkload(parentWorkload string) *PodWrapper { 130 p.Annotations[constants.ParentWorkloadAnnotation] = parentWorkload 131 return p 132 } 133 134 // KueueSchedulingGate adds kueue scheduling gate to the Pod 135 func (p *PodWrapper) KueueSchedulingGate() *PodWrapper { 136 if p.Spec.SchedulingGates == nil { 137 p.Spec.SchedulingGates = make([]corev1.PodSchedulingGate, 0) 138 } 139 p.Spec.SchedulingGates = append(p.Spec.SchedulingGates, corev1.PodSchedulingGate{Name: "kueue.x-k8s.io/admission"}) 140 return p 141 } 142 143 // Finalizer adds a finalizer to the Pod 144 func (p *PodWrapper) Finalizer(f string) *PodWrapper { 145 if p.ObjectMeta.Finalizers == nil { 146 p.ObjectMeta.Finalizers = make([]string, 0) 147 } 148 p.ObjectMeta.Finalizers = append(p.ObjectMeta.Finalizers, f) 149 return p 150 } 151 152 // KueueFinalizer adds kueue finalizer to the Pod 153 func (p *PodWrapper) KueueFinalizer() *PodWrapper { 154 return p.Finalizer("kueue.x-k8s.io/managed") 155 } 156 157 // NodeSelector adds a node selector to the Pod. 158 func (p *PodWrapper) NodeSelector(k, v string) *PodWrapper { 159 if p.Spec.NodeSelector == nil { 160 p.Spec.NodeSelector = make(map[string]string, 1) 161 } 162 163 p.Spec.NodeSelector[k] = v 164 return p 165 } 166 167 // Request adds a resource request to the default container. 168 func (p *PodWrapper) Request(r corev1.ResourceName, v string) *PodWrapper { 169 p.Spec.Containers[0].Resources.Requests[r] = resource.MustParse(v) 170 return p 171 } 172 173 func (p *PodWrapper) Image(image string, args []string) *PodWrapper { 174 p.Spec.Containers[0].Image = image 175 p.Spec.Containers[0].Args = args 176 return p 177 } 178 179 // OwnerReference adds a ownerReference to the default container. 180 func (p *PodWrapper) OwnerReference(ownerName string, ownerGVK schema.GroupVersionKind) *PodWrapper { 181 p.ObjectMeta.OwnerReferences = append( 182 p.ObjectMeta.OwnerReferences, 183 metav1.OwnerReference{ 184 APIVersion: ownerGVK.GroupVersion().String(), 185 Kind: ownerGVK.Kind, 186 Name: ownerName, 187 UID: types.UID(ownerName), 188 Controller: ptr.To(true), 189 }, 190 ) 191 192 return p 193 } 194 195 // UID updates the uid of the Pod. 196 func (p *PodWrapper) UID(uid string) *PodWrapper { 197 p.ObjectMeta.UID = types.UID(uid) 198 return p 199 } 200 201 // StatusConditions updates status conditions of the Pod. 202 func (p *PodWrapper) StatusConditions(conditions ...corev1.PodCondition) *PodWrapper { 203 p.Pod.Status.Conditions = conditions 204 return p 205 } 206 207 // StatusPhase updates status phase of the Pod. 208 func (p *PodWrapper) StatusPhase(ph corev1.PodPhase) *PodWrapper { 209 p.Pod.Status.Phase = ph 210 return p 211 } 212 213 // CreationTimestamp sets a creation timestamp for the pod object 214 func (p *PodWrapper) CreationTimestamp(t time.Time) *PodWrapper { 215 timestamp := metav1.NewTime(t).Rfc3339Copy() 216 p.Pod.CreationTimestamp = timestamp 217 return p 218 } 219 220 // DeletionTimestamp sets a creation timestamp for the pod object 221 func (p *PodWrapper) DeletionTimestamp(t time.Time) *PodWrapper { 222 timestamp := metav1.NewTime(t).Rfc3339Copy() 223 p.Pod.DeletionTimestamp = ×tamp 224 return p 225 } 226 227 // Delete sets a deletion timestamp for the pod object 228 func (p *PodWrapper) Delete() *PodWrapper { 229 t := metav1.NewTime(time.Now()) 230 p.Pod.DeletionTimestamp = &t 231 return p 232 } 233 234 // Volume adds a new volume for the pod object 235 func (p *PodWrapper) Volume(v corev1.Volume) *PodWrapper { 236 p.Pod.Spec.Volumes = append(p.Pod.Spec.Volumes, v) 237 return p 238 }