volcano.sh/volcano@v1.9.0/test/e2e/jobseq/job_plugins.go (about) 1 /* 2 Copyright 2021 The Volcano 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 jobseq 18 19 import ( 20 "context" 21 "fmt" 22 "strings" 23 24 . "github.com/onsi/ginkgo/v2" 25 . "github.com/onsi/gomega" 26 27 cv1 "k8s.io/api/core/v1" 28 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 30 batch "volcano.sh/apis/pkg/apis/batch/v1alpha1" 31 "volcano.sh/volcano/pkg/controllers/job/helpers" 32 "volcano.sh/volcano/pkg/controllers/job/plugins/env" 33 "volcano.sh/volcano/pkg/controllers/job/plugins/svc" 34 35 e2eutil "volcano.sh/volcano/test/e2e/util" 36 ) 37 38 var _ = Describe("Job E2E Test: Test Job Plugins", func() { 39 It("Test SVC Plugin with Node Affinity", func() { 40 jobName := "job-with-svc-plugin" 41 taskName := "task" 42 foundVolume := false 43 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 44 defer e2eutil.CleanupTestContext(ctx) 45 46 nodeName, rep := e2eutil.ComputeNode(ctx, e2eutil.OneCPU) 47 Expect(rep).NotTo(Equal(0)) 48 49 affinity := &cv1.Affinity{ 50 NodeAffinity: &cv1.NodeAffinity{ 51 RequiredDuringSchedulingIgnoredDuringExecution: &cv1.NodeSelector{ 52 NodeSelectorTerms: []cv1.NodeSelectorTerm{ 53 { 54 MatchFields: []cv1.NodeSelectorRequirement{ 55 { 56 Key: "metadata.name", 57 Operator: cv1.NodeSelectorOpIn, 58 Values: []string{nodeName}, 59 }, 60 }, 61 }, 62 }, 63 }, 64 }, 65 } 66 67 job := e2eutil.CreateJob(ctx, &e2eutil.JobSpec{ 68 Namespace: ctx.Namespace, 69 Name: jobName, 70 Plugins: map[string][]string{ 71 "svc": {}, 72 }, 73 Tasks: []e2eutil.TaskSpec{ 74 { 75 Img: e2eutil.DefaultNginxImage, 76 Req: e2eutil.OneCPU, 77 Min: 1, 78 Rep: 1, 79 Name: taskName, 80 Affinity: affinity, 81 }, 82 }, 83 }) 84 85 err := e2eutil.WaitJobReady(ctx, job) 86 Expect(err).NotTo(HaveOccurred()) 87 88 pluginName := fmt.Sprintf("%s-svc", jobName) 89 _, err = ctx.Kubeclient.CoreV1().ConfigMaps(ctx.Namespace).Get(context.TODO(), 90 pluginName, v1.GetOptions{}) 91 Expect(err).NotTo(HaveOccurred()) 92 93 pod, err := ctx.Kubeclient.CoreV1().Pods(ctx.Namespace).Get(context.TODO(), 94 fmt.Sprintf(helpers.PodNameFmt, jobName, taskName, 0), v1.GetOptions{}) 95 Expect(err).NotTo(HaveOccurred()) 96 for _, volume := range pod.Spec.Volumes { 97 if volume.Name == pluginName { 98 foundVolume = true 99 break 100 } 101 } 102 Expect(foundVolume).To(BeTrue()) 103 104 pods := e2eutil.GetTasksOfJob(ctx, job) 105 for _, pod := range pods { 106 Expect(pod.Spec.NodeName).To(Equal(nodeName)) 107 } 108 }) 109 110 It("Test SSh Plugin with Pod Affinity", func() { 111 jobName := "job-with-ssh-plugin" 112 taskName := "task" 113 foundVolume := false 114 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 115 defer e2eutil.CleanupTestContext(ctx) 116 117 _, rep := e2eutil.ComputeNode(ctx, e2eutil.OneCPU) 118 Expect(rep).NotTo(Equal(0)) 119 120 labels := map[string]string{"foo": "bar"} 121 122 affinity := &cv1.Affinity{ 123 PodAffinity: &cv1.PodAffinity{ 124 RequiredDuringSchedulingIgnoredDuringExecution: []cv1.PodAffinityTerm{ 125 { 126 LabelSelector: &v1.LabelSelector{ 127 MatchLabels: labels, 128 }, 129 TopologyKey: "kubernetes.io/hostname", 130 }, 131 }, 132 }, 133 } 134 135 job := e2eutil.CreateJob(ctx, &e2eutil.JobSpec{ 136 Namespace: ctx.Namespace, 137 Name: jobName, 138 Plugins: map[string][]string{ 139 "ssh": {"--no-root"}, 140 }, 141 Tasks: []e2eutil.TaskSpec{ 142 { 143 Img: e2eutil.DefaultNginxImage, 144 Req: e2eutil.HalfCPU, 145 Min: rep, 146 Rep: rep, 147 Affinity: affinity, 148 Labels: labels, 149 Name: taskName, 150 }, 151 }, 152 }) 153 154 err := e2eutil.WaitJobReady(ctx, job) 155 Expect(err).NotTo(HaveOccurred()) 156 157 secretName := genSSHSecretName(job) 158 _, err = ctx.Kubeclient.CoreV1().Secrets(ctx.Namespace).Get(context.TODO(), 159 secretName, v1.GetOptions{}) 160 Expect(err).NotTo(HaveOccurred()) 161 162 pod, err := ctx.Kubeclient.CoreV1().Pods(ctx.Namespace).Get(context.TODO(), 163 fmt.Sprintf(helpers.PodNameFmt, jobName, taskName, 0), v1.GetOptions{}) 164 Expect(err).NotTo(HaveOccurred()) 165 for _, volume := range pod.Spec.Volumes { 166 if volume.Name == secretName { 167 foundVolume = true 168 break 169 } 170 } 171 Expect(foundVolume).To(BeTrue()) 172 173 pods := e2eutil.GetTasksOfJob(ctx, job) 174 // All pods should be scheduled to the same node. 175 nodeName := pods[0].Spec.NodeName 176 for _, pod := range pods { 177 Expect(pod.Spec.NodeName).To(Equal(nodeName)) 178 } 179 }) 180 181 It("Test SVC Plugin with disableNetworkPolicy", func() { 182 jobName := "svc-with-disable-network-policy" 183 taskName := "task" 184 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 185 defer e2eutil.CleanupTestContext(ctx) 186 187 _, rep := e2eutil.ComputeNode(ctx, e2eutil.OneCPU) 188 Expect(rep).NotTo(Equal(0)) 189 190 job := e2eutil.CreateJob(ctx, &e2eutil.JobSpec{ 191 Namespace: ctx.Namespace, 192 Name: jobName, 193 Plugins: map[string][]string{ 194 "svc": {"--disable-network-policy=true"}, 195 }, 196 Tasks: []e2eutil.TaskSpec{ 197 { 198 Img: e2eutil.DefaultNginxImage, 199 Req: e2eutil.OneCPU, 200 Min: 1, 201 Rep: rep, 202 Name: taskName, 203 }, 204 }, 205 }) 206 207 err := e2eutil.WaitJobReady(ctx, job) 208 Expect(err).NotTo(HaveOccurred()) 209 210 // Check whether network policy is created with job name 211 networkPolicyName := jobName 212 _, err = ctx.Kubeclient.NetworkingV1().NetworkPolicies(ctx.Namespace).Get(context.TODO(), networkPolicyName, v1.GetOptions{}) 213 // Error will occur because there is no policy should be created 214 Expect(err).To(HaveOccurred()) 215 }) 216 217 It("Check Functionality of all plugins", func() { 218 jobName := "job-with-all-plugin" 219 taskName := "task" 220 foundVolume := false 221 foundEnv := false 222 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 223 defer e2eutil.CleanupTestContext(ctx) 224 225 _, rep := e2eutil.ComputeNode(ctx, e2eutil.OneCPU) 226 Expect(rep).NotTo(Equal(0)) 227 228 job := e2eutil.CreateJob(ctx, &e2eutil.JobSpec{ 229 Namespace: ctx.Namespace, 230 Name: jobName, 231 Plugins: map[string][]string{ 232 "ssh": {"--no-root"}, 233 "env": {}, 234 "svc": {}, 235 }, 236 Tasks: []e2eutil.TaskSpec{ 237 { 238 Img: e2eutil.DefaultNginxImage, 239 Req: e2eutil.OneCPU, 240 Min: 1, 241 Rep: rep, 242 Name: taskName, 243 }, 244 }, 245 }) 246 247 err := e2eutil.WaitJobReady(ctx, job) 248 Expect(err).NotTo(HaveOccurred()) 249 250 secretName := genSSHSecretName(job) 251 _, err = ctx.Kubeclient.CoreV1().Secrets(ctx.Namespace).Get(context.TODO(), 252 secretName, v1.GetOptions{}) 253 Expect(err).NotTo(HaveOccurred()) 254 255 pod, err := ctx.Kubeclient.CoreV1().Pods(ctx.Namespace).Get(context.TODO(), 256 fmt.Sprintf(helpers.PodNameFmt, jobName, taskName, 0), v1.GetOptions{}) 257 Expect(err).NotTo(HaveOccurred()) 258 for _, volume := range pod.Spec.Volumes { 259 if volume.Name == secretName { 260 foundVolume = true 261 break 262 } 263 } 264 Expect(foundVolume).To(BeTrue()) 265 266 // Check whether env exists in the containers and initContainers 267 containers := pod.Spec.Containers 268 containers = append(containers, pod.Spec.InitContainers...) 269 envNames := []string{ 270 env.TaskVkIndex, 271 env.TaskIndex, 272 fmt.Sprintf(svc.EnvTaskHostFmt, strings.ToUpper(taskName)), 273 fmt.Sprintf(svc.EnvHostNumFmt, strings.ToUpper(taskName)), 274 } 275 276 for _, container := range containers { 277 for _, name := range envNames { 278 foundEnv = false 279 for _, envi := range container.Env { 280 if envi.Name == name { 281 foundEnv = true 282 break 283 } 284 } 285 286 Expect(foundEnv).To(BeTrue(), 287 fmt.Sprintf("container: %s, env name: %s", container.Name, name)) 288 } 289 } 290 291 // Check whether service is created with job name 292 _, err = ctx.Kubeclient.CoreV1().Services(job.Namespace).Get(context.TODO(), job.Name, v1.GetOptions{}) 293 Expect(err).NotTo(HaveOccurred()) 294 }) 295 }) 296 297 func genSSHSecretName(job *batch.Job) string { 298 return job.Name + "-ssh" 299 }