k8s.io/kubernetes@v1.31.0-alpha.0.0.20240520171757-56147500dadc/test/e2e/framework/job/fixtures.go (about) 1 /* 2 Copyright 2019 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 job 18 19 import ( 20 batchv1 "k8s.io/api/batch/v1" 21 v1 "k8s.io/api/core/v1" 22 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 "k8s.io/apimachinery/pkg/util/rand" 24 "k8s.io/kubernetes/test/e2e/framework" 25 imageutils "k8s.io/kubernetes/test/utils/image" 26 "k8s.io/utils/ptr" 27 ) 28 29 // NewTestJob returns a Job which does one of several testing behaviors. notTerminate starts a Job that will run 30 // effectively forever. fail starts a Job that will fail immediately. succeed starts a Job that will succeed 31 // immediately. randomlySucceedOrFail starts a Job that will succeed or fail randomly. failOnce fails the Job the 32 // first time it is run and succeeds subsequently. name is the Name of the Job. RestartPolicy indicates the restart 33 // policy of the containers in which the Pod is running. Parallelism is the Job's parallelism, and completions is the 34 // Job's required number of completions. 35 func NewTestJob(behavior, name string, rPol v1.RestartPolicy, parallelism, completions int32, activeDeadlineSeconds *int64, backoffLimit int32) *batchv1.Job { 36 anyNode := "" 37 return NewTestJobOnNode(behavior, name, rPol, parallelism, completions, activeDeadlineSeconds, backoffLimit, anyNode) 38 } 39 40 // NewTestJobOnNode is similar to NewTestJob but supports specifying a Node on which the Job's Pods will run. 41 // Empty nodeName means no node selection constraints. 42 func NewTestJobOnNode(behavior, name string, rPol v1.RestartPolicy, parallelism, completions int32, activeDeadlineSeconds *int64, backoffLimit int32, nodeName string) *batchv1.Job { 43 manualSelector := false 44 job := &batchv1.Job{ 45 ObjectMeta: metav1.ObjectMeta{ 46 Name: name, 47 }, 48 TypeMeta: metav1.TypeMeta{ 49 Kind: "Job", 50 }, 51 Spec: batchv1.JobSpec{ 52 ActiveDeadlineSeconds: activeDeadlineSeconds, 53 Parallelism: ¶llelism, 54 Completions: &completions, 55 BackoffLimit: &backoffLimit, 56 ManualSelector: &manualSelector, 57 Template: v1.PodTemplateSpec{ 58 ObjectMeta: metav1.ObjectMeta{ 59 Labels: map[string]string{JobSelectorKey: name}, 60 }, 61 Spec: v1.PodSpec{ 62 RestartPolicy: rPol, 63 Volumes: []v1.Volume{ 64 { 65 Name: "data", 66 VolumeSource: v1.VolumeSource{ 67 EmptyDir: &v1.EmptyDirVolumeSource{}, 68 }, 69 }, 70 }, 71 Containers: []v1.Container{ 72 { 73 Name: "c", 74 Image: imageutils.GetE2EImage(imageutils.BusyBox), 75 Command: []string{}, 76 VolumeMounts: []v1.VolumeMount{ 77 { 78 MountPath: "/data", 79 Name: "data", 80 }, 81 }, 82 SecurityContext: &v1.SecurityContext{}, 83 }, 84 }, 85 }, 86 }, 87 }, 88 } 89 if len(nodeName) > 0 { 90 job.Spec.Template.Spec.NodeSelector = map[string]string{ 91 "kubernetes.io/hostname": nodeName, 92 } 93 } 94 switch behavior { 95 case "neverTerminate": 96 // this job is being used in an upgrade job see test/e2e/upgrades/apps/job.go 97 // it should never be optimized, as it always has to restart during an upgrade 98 // and continue running 99 job.Spec.Template.Spec.Containers[0].Command = []string{"sleep", "1000000"} 100 job.Spec.Template.Spec.TerminationGracePeriodSeconds = ptr.To(int64(1)) 101 case "notTerminate": 102 job.Spec.Template.Spec.Containers[0].Image = imageutils.GetPauseImageName() 103 case "fail": 104 job.Spec.Template.Spec.Containers[0].Command = []string{"/bin/sh", "-c", "exit 1"} 105 case "failOddSucceedEven": 106 job.Spec.Template.Spec.Containers[0].Command = []string{"sh", "-c"} 107 job.Spec.Template.Spec.Containers[0].Args = []string{` 108 if [ $(expr ${JOB_COMPLETION_INDEX} % 2) -ne 0 ]; then 109 exit 1 110 else 111 exit 0 112 fi 113 `, 114 } 115 case "succeed": 116 job.Spec.Template.Spec.Containers[0].Command = []string{"/bin/sh", "-c", "exit 0"} 117 case "randomlySucceedOrFail": 118 // Bash's $RANDOM generates pseudorandom int in range 0 - 32767. 119 // Dividing by 16384 gives roughly 50/50 chance of success. 120 job.Spec.Template.Spec.Containers[0].Command = []string{"/bin/sh", "-c", "exit $(( $RANDOM / 16384 ))"} 121 case "failOnce": 122 // Fail the first the container of the pod is run, and 123 // succeed the second time. Checks for file on a data volume. 124 // If present, succeed. If not, create but fail. 125 // If RestartPolicy is Never, the nodeName should be set to 126 // ensure all job pods run on a single node and the volume 127 // will be mounted from a hostPath instead. 128 setupHostPathDirectory(job) 129 job.Spec.Template.Spec.Containers[0].Command = []string{"/bin/sh", "-c", "if [[ -r /data/foo ]] ; then exit 0 ; else touch /data/foo ; exit 1 ; fi"} 130 case "notTerminateOnce": 131 // Do not terminate the 0-indexed pod in the first run and 132 // succeed the second time. Fail the non-0-indexed pods until 133 // the marker file is created by the 0-indexed pod. The fact that 134 // the non-0-indexed pods are succeeded is used to determine that the 135 // 0th indexed pod already created the marker file. 136 setupHostPathDirectory(job) 137 job.Spec.Template.Spec.TerminationGracePeriodSeconds = ptr.To(int64(1)) 138 job.Spec.Template.Spec.Containers[0].Command = []string{"/bin/sh", "-c", "if [[ -r /data/foo ]] ; then exit 0 ; elif [[ $JOB_COMPLETION_INDEX -eq 0 ]] ; then touch /data/foo ; sleep 1000000 ; else exit 1 ; fi"} 139 } 140 return job 141 } 142 143 // setup host path directory to pass information between pod restarts 144 func setupHostPathDirectory(job *batchv1.Job) { 145 if _, nodeNameSpecified := job.Spec.Template.Spec.NodeSelector["kubernetes.io/hostname"]; nodeNameSpecified { 146 randomDir := "/tmp/job-e2e/" + rand.String(10) 147 hostPathType := v1.HostPathDirectoryOrCreate 148 job.Spec.Template.Spec.Volumes[0].VolumeSource = v1.VolumeSource{HostPath: &v1.HostPathVolumeSource{Path: randomDir, Type: &hostPathType}} 149 // Tests involving r/w operations on hostPath volume needs to run in 150 // privileged mode for SELinux enabled distro, while Windows platform 151 // neither supports nor needs privileged mode. 152 privileged := !framework.NodeOSDistroIs("windows") 153 job.Spec.Template.Spec.Containers[0].SecurityContext.Privileged = &privileged 154 } 155 }