sigs.k8s.io/kueue@v0.6.2/pkg/util/testingjobs/job/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  	"time"
    21  
    22  	batchv1 "k8s.io/api/batch/v1"
    23  	corev1 "k8s.io/api/core/v1"
    24  	"k8s.io/apimachinery/pkg/api/resource"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/apimachinery/pkg/runtime/schema"
    27  	"k8s.io/apimachinery/pkg/types"
    28  	"k8s.io/utils/ptr"
    29  
    30  	"sigs.k8s.io/kueue/pkg/controller/constants"
    31  )
    32  
    33  // JobWrapper wraps a Job.
    34  type JobWrapper struct{ batchv1.Job }
    35  
    36  // MakeJob creates a wrapper for a suspended job with a single container and parallelism=1.
    37  func MakeJob(name, ns string) *JobWrapper {
    38  	return &JobWrapper{batchv1.Job{
    39  		ObjectMeta: metav1.ObjectMeta{
    40  			Name:        name,
    41  			Namespace:   ns,
    42  			Annotations: make(map[string]string, 1),
    43  		},
    44  		Spec: batchv1.JobSpec{
    45  			Parallelism: ptr.To[int32](1),
    46  			Suspend:     ptr.To(true),
    47  			Template: corev1.PodTemplateSpec{
    48  				Spec: corev1.PodSpec{
    49  					RestartPolicy: corev1.RestartPolicyNever,
    50  					Containers: []corev1.Container{
    51  						{
    52  							Name:      "c",
    53  							Image:     "pause",
    54  							Resources: corev1.ResourceRequirements{Requests: corev1.ResourceList{}},
    55  						},
    56  					},
    57  					NodeSelector: map[string]string{},
    58  				},
    59  			},
    60  		},
    61  	}}
    62  }
    63  
    64  // Obj returns the inner Job.
    65  func (j *JobWrapper) Obj() *batchv1.Job {
    66  	return &j.Job
    67  }
    68  
    69  // Clone returns deep copy of the Job.
    70  func (j *JobWrapper) Clone() *JobWrapper {
    71  	return &JobWrapper{Job: *j.DeepCopy()}
    72  }
    73  
    74  func (j *JobWrapper) BackoffLimit(limit int32) *JobWrapper {
    75  	j.Spec.BackoffLimit = ptr.To(limit)
    76  	return j
    77  }
    78  
    79  func (j *JobWrapper) TerminationGracePeriod(seconds int64) *JobWrapper {
    80  	j.Spec.Template.Spec.TerminationGracePeriodSeconds = ptr.To(seconds)
    81  	return j
    82  }
    83  
    84  // Suspend updates the suspend status of the job
    85  func (j *JobWrapper) Suspend(s bool) *JobWrapper {
    86  	j.Spec.Suspend = ptr.To(s)
    87  	return j
    88  }
    89  
    90  // Parallelism updates job parallelism.
    91  func (j *JobWrapper) Parallelism(p int32) *JobWrapper {
    92  	j.Spec.Parallelism = ptr.To(p)
    93  	return j
    94  }
    95  
    96  // Completions updates job completions.
    97  func (j *JobWrapper) Completions(p int32) *JobWrapper {
    98  	j.Spec.Completions = ptr.To(p)
    99  	return j
   100  }
   101  
   102  // Indexed sets the job's completion to Indexed of NonIndexed
   103  func (j *JobWrapper) Indexed(indexed bool) *JobWrapper {
   104  	mode := batchv1.NonIndexedCompletion
   105  	if indexed {
   106  		mode = batchv1.IndexedCompletion
   107  	}
   108  	j.Spec.CompletionMode = &mode
   109  	return j
   110  }
   111  
   112  // PriorityClass updates job priorityclass.
   113  func (j *JobWrapper) PriorityClass(pc string) *JobWrapper {
   114  	j.Spec.Template.Spec.PriorityClassName = pc
   115  	return j
   116  }
   117  
   118  // WorkloadPriorityClass updates job workloadpriorityclass.
   119  func (j *JobWrapper) WorkloadPriorityClass(wpc string) *JobWrapper {
   120  	return j.Label(constants.WorkloadPriorityClassLabel, wpc)
   121  }
   122  
   123  // Queue updates the queue name of the job
   124  func (j *JobWrapper) Queue(queue string) *JobWrapper {
   125  	return j.Label(constants.QueueLabel, queue)
   126  }
   127  
   128  // Label sets the label key and value
   129  func (j *JobWrapper) Label(key, value string) *JobWrapper {
   130  	if j.Labels == nil {
   131  		j.Labels = make(map[string]string)
   132  	}
   133  	j.Labels[key] = value
   134  	return j
   135  }
   136  
   137  // QueueNameAnnotation updates the queue name of the job by annotation (deprecated)
   138  func (j *JobWrapper) QueueNameAnnotation(queue string) *JobWrapper {
   139  	return j.SetAnnotation(constants.QueueAnnotation, queue)
   140  }
   141  
   142  // ParentWorkload sets the parent-workload annotation
   143  func (j *JobWrapper) ParentWorkload(parentWorkload string) *JobWrapper {
   144  	j.Annotations[constants.ParentWorkloadAnnotation] = parentWorkload
   145  	return j
   146  }
   147  
   148  func (j *JobWrapper) SetAnnotation(key, content string) *JobWrapper {
   149  	j.Annotations[key] = content
   150  	return j
   151  }
   152  
   153  // Toleration adds a toleration to the job.
   154  func (j *JobWrapper) Toleration(t corev1.Toleration) *JobWrapper {
   155  	j.Spec.Template.Spec.Tolerations = append(j.Spec.Template.Spec.Tolerations, t)
   156  	return j
   157  }
   158  
   159  // NodeSelector adds a node selector to the job.
   160  func (j *JobWrapper) NodeSelector(k, v string) *JobWrapper {
   161  	j.Spec.Template.Spec.NodeSelector[k] = v
   162  	return j
   163  }
   164  
   165  // PodAnnotation sets annotation at the pod template level
   166  func (j *JobWrapper) PodAnnotation(k, v string) *JobWrapper {
   167  	if j.Spec.Template.Annotations == nil {
   168  		j.Spec.Template.Annotations = make(map[string]string)
   169  	}
   170  	j.Spec.Template.Annotations[k] = v
   171  	return j
   172  }
   173  
   174  // PodLabel sets label at the pod template level
   175  func (j *JobWrapper) PodLabel(k, v string) *JobWrapper {
   176  	if j.Spec.Template.Labels == nil {
   177  		j.Spec.Template.Labels = make(map[string]string)
   178  	}
   179  	j.Spec.Template.Labels[k] = v
   180  	return j
   181  }
   182  
   183  // Request adds a resource request to the default container.
   184  func (j *JobWrapper) Request(r corev1.ResourceName, v string) *JobWrapper {
   185  	j.Spec.Template.Spec.Containers[0].Resources.Requests[r] = resource.MustParse(v)
   186  	return j
   187  }
   188  
   189  func (j *JobWrapper) Image(image string, args []string) *JobWrapper {
   190  	j.Spec.Template.Spec.Containers[0].Image = image
   191  	j.Spec.Template.Spec.Containers[0].Args = args
   192  	return j
   193  }
   194  
   195  // OwnerReference adds a ownerReference to the default container.
   196  func (j *JobWrapper) OwnerReference(ownerName string, ownerGVK schema.GroupVersionKind) *JobWrapper {
   197  	j.ObjectMeta.OwnerReferences = []metav1.OwnerReference{
   198  		{
   199  			APIVersion: ownerGVK.GroupVersion().String(),
   200  			Kind:       ownerGVK.Kind,
   201  			Name:       ownerName,
   202  			UID:        types.UID(ownerName),
   203  			Controller: ptr.To(true),
   204  		},
   205  	}
   206  	return j
   207  }
   208  
   209  func (j *JobWrapper) Containers(containers ...corev1.Container) *JobWrapper {
   210  	j.Spec.Template.Spec.Containers = containers
   211  	return j
   212  }
   213  
   214  // UID updates the uid of the job.
   215  func (j *JobWrapper) UID(uid string) *JobWrapper {
   216  	j.ObjectMeta.UID = types.UID(uid)
   217  	return j
   218  }
   219  
   220  // StartTime sets the .status.startTime
   221  func (j *JobWrapper) StartTime(t time.Time) *JobWrapper {
   222  	j.Status.StartTime = &metav1.Time{Time: t}
   223  	return j
   224  }
   225  
   226  // Active sets the .status.active
   227  func (j *JobWrapper) Active(c int32) *JobWrapper {
   228  	j.Status.Active = c
   229  	return j
   230  }
   231  
   232  // Condition adds a condition
   233  func (j *JobWrapper) Condition(c batchv1.JobCondition) *JobWrapper {
   234  	j.Status.Conditions = append(j.Status.Conditions, c)
   235  	return j
   236  }
   237  
   238  func SetContainerDefaults(c *corev1.Container) {
   239  	if c.TerminationMessagePath == "" {
   240  		c.TerminationMessagePath = "/dev/termination-log"
   241  	}
   242  
   243  	if c.TerminationMessagePolicy == "" {
   244  		c.TerminationMessagePolicy = corev1.TerminationMessageReadFile
   245  	}
   246  
   247  	if c.ImagePullPolicy == "" {
   248  		c.ImagePullPolicy = corev1.PullIfNotPresent
   249  	}
   250  }