volcano.sh/volcano@v1.9.0/test/e2e/jobp/admission.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 jobp 18 19 import ( 20 "context" 21 "encoding/json" 22 23 "github.com/onsi/ginkgo/v2" 24 "github.com/onsi/gomega" 25 26 corev1 "k8s.io/api/core/v1" 27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 28 v1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 30 "volcano.sh/apis/pkg/apis/batch/v1alpha1" 31 schedulingv1beta1 "volcano.sh/apis/pkg/apis/scheduling/v1beta1" 32 vcschedulingv1 "volcano.sh/apis/pkg/apis/scheduling/v1beta1" 33 34 e2eutil "volcano.sh/volcano/test/e2e/util" 35 ) 36 37 var _ = ginkgo.Describe("Job E2E Test: Test Admission service", func() { 38 39 ginkgo.It("Default queue would be added", func() { 40 jobName := "job-default-queue" 41 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 42 defer e2eutil.CleanupTestContext(ctx) 43 44 _, err := e2eutil.CreateJobInner(ctx, &e2eutil.JobSpec{ 45 Min: 1, 46 Namespace: ctx.Namespace, 47 Name: jobName, 48 Tasks: []e2eutil.TaskSpec{ 49 { 50 Img: e2eutil.DefaultNginxImage, 51 Req: e2eutil.OneCPU, 52 Min: 1, 53 Rep: 1, 54 Name: "taskname", 55 }, 56 }, 57 }) 58 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 59 createdJob, err := ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Get(context.TODO(), jobName, v1.GetOptions{}) 60 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 61 gomega.Expect(createdJob.Spec.Queue).Should(gomega.Equal("default"), 62 "Job queue attribute would default to 'default' ") 63 }) 64 65 ginkgo.It("Invalid CPU unit", func() { 66 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 67 defer e2eutil.CleanupTestContext(ctx) 68 69 var job v1alpha1.Job 70 jsonData := []byte(`{ 71 "apiVersion": "batch.volcano.sh/v1alpha1", 72 "kind": "Job", 73 "metadata": { 74 "name": "test-job" 75 }, 76 "spec": { 77 "minAvailable": 3, 78 "schedulerName": "volcano", 79 "queue": "default", 80 "tasks": [ 81 { 82 "replicas": 3, 83 "name": "default-nginx", 84 "template": { 85 "spec": { 86 "containers": [ 87 { 88 "image": "nginx", 89 "imagePullPolicy": "IfNotPresent", 90 "name": "nginx", 91 "resources": { 92 "requests": { 93 "cpu": "-1" 94 } 95 } 96 } 97 ], 98 "restartPolicy": "Never" 99 } 100 } 101 } 102 ] 103 } 104 }`) 105 err := json.Unmarshal(jsonData, &job) 106 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 107 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 108 gomega.Expect(err).To(gomega.HaveOccurred()) 109 110 }) 111 112 ginkgo.It("Invalid memory unit", func() { 113 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 114 defer e2eutil.CleanupTestContext(ctx) 115 116 var job v1alpha1.Job 117 jsonData := []byte(`{ 118 "apiVersion": "batch.volcano.sh/v1alpha1", 119 "kind": "Job", 120 "metadata": { 121 "name": "test-job" 122 }, 123 "spec": { 124 "minAvailable": 3, 125 "schedulerName": "volcano", 126 "queue": "default", 127 "tasks": [ 128 { 129 "replicas": 3, 130 "name": "default-nginx", 131 "template": { 132 "spec": { 133 "containers": [ 134 { 135 "image": "nginx", 136 "imagePullPolicy": "IfNotPresent", 137 "name": "nginx", 138 "resources": { 139 "requests": { 140 "memory": "-1" 141 } 142 } 143 } 144 ], 145 "restartPolicy": "Never" 146 } 147 } 148 } 149 ] 150 } 151 }`) 152 153 err := json.Unmarshal(jsonData, &job) 154 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 155 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 156 gomega.Expect(err).To(gomega.HaveOccurred()) 157 158 }) 159 160 ginkgo.It("Create default-scheduler pod", func() { 161 podName := "pod-default-scheduler" 162 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 163 defer e2eutil.CleanupTestContext(ctx) 164 165 pod := &corev1.Pod{ 166 TypeMeta: v1.TypeMeta{ 167 APIVersion: "v1", 168 Kind: "Pod", 169 }, 170 ObjectMeta: v1.ObjectMeta{ 171 Namespace: ctx.Namespace, 172 Name: podName, 173 }, 174 Spec: corev1.PodSpec{ 175 Containers: e2eutil.CreateContainers(e2eutil.DefaultNginxImage, "", "", e2eutil.OneCPU, e2eutil.OneCPU, 0), 176 }, 177 } 178 179 _, err := ctx.Kubeclient.CoreV1().Pods(ctx.Namespace).Create(context.TODO(), pod, v1.CreateOptions{}) 180 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 181 182 err = e2eutil.WaitPodPhase(ctx, pod, []corev1.PodPhase{corev1.PodRunning}) 183 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 184 }) 185 186 ginkgo.It("Create volcano-scheduler pod", func() { 187 podName := "pod-volcano-scheduler" 188 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 189 defer e2eutil.CleanupTestContext(ctx) 190 191 pod := &corev1.Pod{ 192 TypeMeta: v1.TypeMeta{ 193 APIVersion: "v1", 194 Kind: "Pod", 195 }, 196 ObjectMeta: v1.ObjectMeta{ 197 Namespace: ctx.Namespace, 198 Name: podName, 199 }, 200 Spec: corev1.PodSpec{ 201 Containers: e2eutil.CreateContainers(e2eutil.DefaultNginxImage, "", "", e2eutil.OneCPU, e2eutil.OneCPU, 0), 202 SchedulerName: "volcano", 203 }, 204 } 205 206 _, err := ctx.Kubeclient.CoreV1().Pods(ctx.Namespace).Create(context.TODO(), pod, v1.CreateOptions{}) 207 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 208 209 err = e2eutil.WaitPodPhase(ctx, pod, []corev1.PodPhase{corev1.PodRunning}) 210 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 211 }) 212 213 ginkgo.It("Create volcano pod with volcano scheduler", func() { 214 podName := "volcano-pod" 215 pgName := "running-pg" 216 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 217 defer e2eutil.CleanupTestContext(ctx) 218 219 pg := &schedulingv1beta1.PodGroup{ 220 ObjectMeta: v1.ObjectMeta{ 221 Namespace: ctx.Namespace, 222 Name: pgName, 223 }, 224 Spec: schedulingv1beta1.PodGroupSpec{ 225 MinMember: 1, 226 MinResources: &e2eutil.OneCPU, 227 }, 228 } 229 230 pod := &corev1.Pod{ 231 TypeMeta: v1.TypeMeta{ 232 APIVersion: "v1", 233 Kind: "Pod", 234 }, 235 ObjectMeta: v1.ObjectMeta{ 236 Namespace: ctx.Namespace, 237 Name: podName, 238 Annotations: map[string]string{vcschedulingv1.KubeGroupNameAnnotationKey: pgName}, 239 }, 240 Spec: corev1.PodSpec{ 241 Containers: e2eutil.CreateContainers(e2eutil.DefaultNginxImage, "", "", e2eutil.HalfCPU, e2eutil.HalfCPU, 0), 242 SchedulerName: "volcano", 243 }, 244 } 245 246 podGroup, err := ctx.Vcclient.SchedulingV1beta1().PodGroups(ctx.Namespace).Create(context.TODO(), pg, v1.CreateOptions{}) 247 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 248 err = e2eutil.WaitPodGroupPhase(ctx, podGroup, schedulingv1beta1.PodGroupInqueue) 249 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 250 _, err = ctx.Kubeclient.CoreV1().Pods(ctx.Namespace).Create(context.TODO(), pod, v1.CreateOptions{}) 251 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 252 err = e2eutil.WaitPodPhase(ctx, pod, []corev1.PodPhase{corev1.PodRunning}) 253 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 254 }) 255 256 ginkgo.It("Allow to create pod when podgroup is Pending", func() { 257 podName := "pod-volcano" 258 pgName := "pending-pg" 259 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 260 defer e2eutil.CleanupTestContext(ctx) 261 262 pg := &schedulingv1beta1.PodGroup{ 263 ObjectMeta: v1.ObjectMeta{ 264 Namespace: ctx.Namespace, 265 Name: pgName, 266 }, 267 Spec: schedulingv1beta1.PodGroupSpec{ 268 MinMember: 1, 269 MinResources: &e2eutil.ThirtyCPU, 270 }, 271 Status: schedulingv1beta1.PodGroupStatus{ 272 Phase: schedulingv1beta1.PodGroupPending, 273 }, 274 } 275 276 pod := &corev1.Pod{ 277 TypeMeta: v1.TypeMeta{ 278 APIVersion: "v1", 279 Kind: "Pod", 280 }, 281 ObjectMeta: v1.ObjectMeta{ 282 Namespace: ctx.Namespace, 283 Name: podName, 284 Annotations: map[string]string{schedulingv1beta1.KubeGroupNameAnnotationKey: pgName}, 285 }, 286 Spec: corev1.PodSpec{ 287 SchedulerName: "volcano", 288 Containers: e2eutil.CreateContainers(e2eutil.DefaultNginxImage, "", "", e2eutil.OneCPU, e2eutil.OneCPU, 0), 289 }, 290 } 291 292 _, err := ctx.Vcclient.SchedulingV1beta1().PodGroups(ctx.Namespace).Create(context.TODO(), pg, v1.CreateOptions{}) 293 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 294 295 _, err = ctx.Kubeclient.CoreV1().Pods(ctx.Namespace).Create(context.TODO(), pod, v1.CreateOptions{}) 296 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 297 }) 298 299 ginkgo.It("Job mutate check", func() { 300 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 301 defer e2eutil.CleanupTestContext(ctx) 302 303 var job v1alpha1.Job 304 jsonData := []byte(`{ 305 "apiVersion": "batch.volcano.sh/v1alpha1", 306 "kind": "Job", 307 "metadata": { 308 "name": "test-job" 309 }, 310 "spec": { 311 "minAvailable": 1, 312 "tasks": [ 313 { 314 "replicas": 1, 315 "template": { 316 "spec": { 317 "containers": [ 318 { 319 "image": "nginx", 320 "imagePullPolicy": "IfNotPresent", 321 "name": "nginx", 322 "resources": { 323 "requests": { 324 "cpu": "1" 325 } 326 } 327 } 328 ], 329 "restartPolicy": "Never" 330 } 331 } 332 }, 333 { 334 "replicas": 1, 335 "template": { 336 "spec": { 337 "containers": [ 338 { 339 "image": "busybox:1.24", 340 "imagePullPolicy": "IfNotPresent", 341 "name": "busybox", 342 "resources": { 343 "requests": { 344 "cpu": "1" 345 } 346 } 347 } 348 ], 349 "restartPolicy": "Never" 350 } 351 } 352 } 353 ] 354 } 355 }`) 356 err := json.Unmarshal(jsonData, &job) 357 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 358 testJob, err := ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 359 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 360 gomega.Expect(testJob.Spec.Queue).Should(gomega.Equal("default"), "Job queue attribute would default to 'default' ") 361 gomega.Expect(testJob.Spec.SchedulerName).Should(gomega.Equal("volcano"), "Job scheduler wolud default to 'volcano'") 362 gomega.Expect(testJob.Spec.Tasks[0].Name).Should(gomega.Equal("default0"), "task[0].name wolud default to 'default0'") 363 gomega.Expect(testJob.Spec.Tasks[1].Name).Should(gomega.Equal("default1"), "task[1].name wolud default to 'default1'") 364 }) 365 366 ginkgo.It("job validate check: duplicate task name check when create", func() { 367 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 368 defer e2eutil.CleanupTestContext(ctx) 369 370 var job v1alpha1.Job 371 jsonData := []byte(`{ 372 "apiVersion": "batch.volcano.sh/v1alpha1", 373 "kind": "Job", 374 "metadata": { 375 "name": "test-job" 376 }, 377 "spec": { 378 "minAvailable": 1, 379 "tasks": [ 380 { 381 "name": "test", 382 "replicas": 1, 383 "template": { 384 "spec": { 385 "containers": [ 386 { 387 "image": "nginx", 388 "imagePullPolicy": "IfNotPresent", 389 "name": "nginx", 390 "resources": { 391 "requests": { 392 "cpu": "1" 393 } 394 } 395 } 396 ], 397 "restartPolicy": "Never" 398 } 399 } 400 }, 401 { 402 "name": "test", 403 "replicas": 1, 404 "template": { 405 "spec": { 406 "containers": [ 407 { 408 "image": "busybox:1.24", 409 "imagePullPolicy": "IfNotPresent", 410 "name": "busybox", 411 "resources": { 412 "requests": { 413 "cpu": "1" 414 } 415 } 416 } 417 ], 418 "restartPolicy": "Never" 419 } 420 } 421 } 422 ] 423 } 424 }`) 425 err := json.Unmarshal(jsonData, &job) 426 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 427 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 428 gomega.Expect(err).To(gomega.HaveOccurred()) 429 }) 430 431 ginkgo.It("job validate check: duplicate job policy event when create", func() { 432 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 433 defer e2eutil.CleanupTestContext(ctx) 434 435 var job v1alpha1.Job 436 jsonData := []byte(`{ 437 "apiVersion": "batch.volcano.sh/v1alpha1", 438 "kind": "Job", 439 "metadata": { 440 "name": "test-job" 441 }, 442 "spec": { 443 "minAvailable": 1, 444 "tasks": [ 445 { 446 "replicas": 1, 447 "template": { 448 "spec": { 449 "containers": [ 450 { 451 "image": "nginx", 452 "imagePullPolicy": "IfNotPresent", 453 "name": "nginx", 454 "resources": { 455 "requests": { 456 "cpu": "1" 457 } 458 } 459 } 460 ], 461 "restartPolicy": "Never" 462 } 463 } 464 } 465 ], 466 "policies": [ 467 { 468 "event": "PodFailed", 469 "action": "AbortJob" 470 }, 471 { 472 "event": "PodFailed", 473 "action": "RestartJob" 474 } 475 ] 476 } 477 }`) 478 err := json.Unmarshal(jsonData, &job) 479 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 480 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 481 gomega.Expect(err).To(gomega.HaveOccurred()) 482 }) 483 484 ginkgo.It("job validate check: minAvailable larger than replicas when create", func() { 485 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 486 defer e2eutil.CleanupTestContext(ctx) 487 488 var job v1alpha1.Job 489 jsonData := []byte(`{ 490 "apiVersion": "batch.volcano.sh/v1alpha1", 491 "kind": "Job", 492 "metadata": { 493 "name": "test-job" 494 }, 495 "spec": { 496 "minAvailable": 2, 497 "tasks": [ 498 { 499 "replicas": 1, 500 "template": { 501 "spec": { 502 "containers": [ 503 { 504 "image": "nginx", 505 "imagePullPolicy": "IfNotPresent", 506 "name": "nginx", 507 "resources": { 508 "requests": { 509 "cpu": "1" 510 } 511 } 512 } 513 ], 514 "restartPolicy": "Never" 515 } 516 } 517 } 518 ] 519 } 520 }`) 521 err := json.Unmarshal(jsonData, &job) 522 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 523 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 524 gomega.Expect(err).To(gomega.HaveOccurred()) 525 }) 526 527 ginkgo.It("job validate check: illegal plugin when create", func() { 528 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 529 defer e2eutil.CleanupTestContext(ctx) 530 531 var job v1alpha1.Job 532 jsonData := []byte(`{ 533 "apiVersion": "batch.volcano.sh/v1alpha1", 534 "kind": "Job", 535 "metadata": { 536 "name": "test-job" 537 }, 538 "spec": { 539 "minAvailable": 1, 540 "tasks": [ 541 { 542 "replicas": 2, 543 "template": { 544 "spec": { 545 "containers": [ 546 { 547 "image": "nginx", 548 "imagePullPolicy": "IfNotPresent", 549 "name": "nginx", 550 "resources": { 551 "requests": { 552 "cpu": "1" 553 } 554 } 555 } 556 ], 557 "restartPolicy": "Never" 558 } 559 } 560 } 561 ], 562 "plugins": { 563 "big_plugin": [] 564 } 565 } 566 }`) 567 err := json.Unmarshal(jsonData, &job) 568 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 569 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 570 gomega.Expect(err).To(gomega.HaveOccurred()) 571 }) 572 573 ginkgo.It("job validate check: illegal ttl when create", func() { 574 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 575 defer e2eutil.CleanupTestContext(ctx) 576 577 var job v1alpha1.Job 578 jsonData := []byte(`{ 579 "apiVersion": "batch.volcano.sh/v1alpha1", 580 "kind": "Job", 581 "metadata": { 582 "name": "test-job" 583 }, 584 "spec": { 585 "minAvailable": 1, 586 "tasks": [ 587 { 588 "replicas": 2, 589 "template": { 590 "spec": { 591 "containers": [ 592 { 593 "image": "nginx", 594 "imagePullPolicy": "IfNotPresent", 595 "name": "nginx", 596 "resources": { 597 "requests": { 598 "cpu": "1" 599 } 600 } 601 } 602 ], 603 "restartPolicy": "Never" 604 } 605 } 606 } 607 ], 608 "ttlSecondsAfterFinished": -1 609 } 610 }`) 611 err := json.Unmarshal(jsonData, &job) 612 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 613 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 614 gomega.Expect(err).To(gomega.HaveOccurred()) 615 }) 616 617 ginkgo.It("job validate check: illegal minAvailable when create", func() { 618 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 619 defer e2eutil.CleanupTestContext(ctx) 620 621 var job v1alpha1.Job 622 jsonData := []byte(`{ 623 "apiVersion": "batch.volcano.sh/v1alpha1", 624 "kind": "Job", 625 "metadata": { 626 "name": "test-job" 627 }, 628 "spec": { 629 "minAvailable": -1, 630 "tasks": [ 631 { 632 "replicas": 2, 633 "template": { 634 "spec": { 635 "containers": [ 636 { 637 "image": "nginx", 638 "imagePullPolicy": "IfNotPresent", 639 "name": "nginx", 640 "resources": { 641 "requests": { 642 "cpu": "1" 643 } 644 } 645 } 646 ], 647 "restartPolicy": "Never" 648 } 649 } 650 } 651 ] 652 } 653 }`) 654 err := json.Unmarshal(jsonData, &job) 655 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 656 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 657 gomega.Expect(err).To(gomega.HaveOccurred()) 658 }) 659 660 ginkgo.It("job validate check: illegal maxRetry when create", func() { 661 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 662 defer e2eutil.CleanupTestContext(ctx) 663 664 var job v1alpha1.Job 665 jsonData := []byte(`{ 666 "apiVersion": "batch.volcano.sh/v1alpha1", 667 "kind": "Job", 668 "metadata": { 669 "name": "test-job" 670 }, 671 "spec": { 672 "minAvailable": 1, 673 "maxRetry": -1, 674 "tasks": [ 675 { 676 "replicas": 2, 677 "template": { 678 "spec": { 679 "containers": [ 680 { 681 "image": "nginx", 682 "imagePullPolicy": "IfNotPresent", 683 "name": "nginx", 684 "resources": { 685 "requests": { 686 "cpu": "1" 687 } 688 } 689 } 690 ], 691 "restartPolicy": "Never" 692 } 693 } 694 } 695 ] 696 } 697 }`) 698 err := json.Unmarshal(jsonData, &job) 699 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 700 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 701 gomega.Expect(err).To(gomega.HaveOccurred()) 702 }) 703 704 ginkgo.It("job validate check: no task spec when create", func() { 705 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 706 defer e2eutil.CleanupTestContext(ctx) 707 708 var job v1alpha1.Job 709 jsonData := []byte(`{ 710 "apiVersion": "batch.volcano.sh/v1alpha1", 711 "kind": "Job", 712 "metadata": { 713 "name": "test-job" 714 }, 715 "spec": { 716 "minAvailable": 1, 717 "tasks":[] 718 } 719 }`) 720 err := json.Unmarshal(jsonData, &job) 721 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 722 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 723 gomega.Expect(err).To(gomega.HaveOccurred()) 724 }) 725 726 ginkgo.It("job validate check: illegal replicas when create", func() { 727 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 728 defer e2eutil.CleanupTestContext(ctx) 729 730 var job v1alpha1.Job 731 jsonData := []byte(`{ 732 "apiVersion": "batch.volcano.sh/v1alpha1", 733 "kind": "Job", 734 "metadata": { 735 "name": "test-job" 736 }, 737 "spec": { 738 "minAvailable": 1, 739 "tasks": [ 740 { 741 "replicas": -1, 742 "template": { 743 "spec": { 744 "containers": [ 745 { 746 "image": "nginx", 747 "imagePullPolicy": "IfNotPresent", 748 "name": "nginx", 749 "resources": { 750 "requests": { 751 "cpu": "1" 752 } 753 } 754 } 755 ], 756 "restartPolicy": "Never" 757 } 758 } 759 } 760 ] 761 } 762 }`) 763 err := json.Unmarshal(jsonData, &job) 764 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 765 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 766 gomega.Expect(err).To(gomega.HaveOccurred()) 767 }) 768 769 ginkgo.It("job validate check: illegal task name when create", func() { 770 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 771 defer e2eutil.CleanupTestContext(ctx) 772 773 var job v1alpha1.Job 774 jsonData := []byte(`{ 775 "apiVersion": "batch.volcano.sh/v1alpha1", 776 "kind": "Job", 777 "metadata": { 778 "name": "test-job" 779 }, 780 "spec": { 781 "minAvailable": 1, 782 "tasks": [ 783 { 784 "name": "Task-1", 785 "replicas": 2, 786 "template": { 787 "spec": { 788 "containers": [ 789 { 790 "image": "nginx", 791 "imagePullPolicy": "IfNotPresent", 792 "name": "nginx", 793 "resources": { 794 "requests": { 795 "cpu": "1" 796 } 797 } 798 } 799 ], 800 "restartPolicy": "Never" 801 } 802 } 803 } 804 ] 805 } 806 }`) 807 err := json.Unmarshal(jsonData, &job) 808 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 809 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 810 gomega.Expect(err).To(gomega.HaveOccurred()) 811 }) 812 813 ginkgo.It("job validate check: policy event with exit code when create", func() { 814 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 815 defer e2eutil.CleanupTestContext(ctx) 816 817 var job v1alpha1.Job 818 jsonData := []byte(`{ 819 "apiVersion": "batch.volcano.sh/v1alpha1", 820 "kind": "Job", 821 "metadata": { 822 "name": "test-job" 823 }, 824 "spec": { 825 "minAvailable": 1, 826 "tasks": [ 827 { 828 "replicas": 2, 829 "template": { 830 "spec": { 831 "containers": [ 832 { 833 "image": "nginx", 834 "imagePullPolicy": "IfNotPresent", 835 "name": "nginx", 836 "resources": { 837 "requests": { 838 "cpu": "1" 839 } 840 } 841 } 842 ], 843 "restartPolicy": "Never" 844 } 845 } 846 } 847 ], 848 "policies": [ 849 { 850 "event": "PodFailed", 851 "action": "AbortJob", 852 "exitCode": -1 853 } 854 ] 855 } 856 }`) 857 err := json.Unmarshal(jsonData, &job) 858 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 859 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 860 gomega.Expect(err).To(gomega.HaveOccurred()) 861 }) 862 863 ginkgo.It("job validate check: policy event and exit code both nil when create", func() { 864 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 865 defer e2eutil.CleanupTestContext(ctx) 866 867 var job v1alpha1.Job 868 jsonData := []byte(`{ 869 "apiVersion": "batch.volcano.sh/v1alpha1", 870 "kind": "Job", 871 "metadata": { 872 "name": "test-job" 873 }, 874 "spec": { 875 "minAvailable": 1, 876 "tasks": [ 877 { 878 "replicas": 2, 879 "template": { 880 "spec": { 881 "containers": [ 882 { 883 "image": "nginx", 884 "imagePullPolicy": "IfNotPresent", 885 "name": "nginx", 886 "resources": { 887 "requests": { 888 "cpu": "1" 889 } 890 } 891 } 892 ], 893 "restartPolicy": "Never" 894 } 895 } 896 } 897 ], 898 "policies": [ 899 { 900 "action": "AbortJob" 901 } 902 ] 903 } 904 }`) 905 err := json.Unmarshal(jsonData, &job) 906 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 907 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 908 gomega.Expect(err).To(gomega.HaveOccurred()) 909 }) 910 911 ginkgo.It("job validate check: invalid policy event when create", func() { 912 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 913 defer e2eutil.CleanupTestContext(ctx) 914 915 var job v1alpha1.Job 916 jsonData := []byte(`{ 917 "apiVersion": "batch.volcano.sh/v1alpha1", 918 "kind": "Job", 919 "metadata": { 920 "name": "test-job" 921 }, 922 "spec": { 923 "minAvailable": 1, 924 "tasks": [ 925 { 926 "replicas": 2, 927 "template": { 928 "spec": { 929 "containers": [ 930 { 931 "image": "nginx", 932 "imagePullPolicy": "IfNotPresent", 933 "name": "nginx", 934 "resources": { 935 "requests": { 936 "cpu": "1" 937 } 938 } 939 } 940 ], 941 "restartPolicy": "Never" 942 } 943 } 944 } 945 ], 946 "policies": [ 947 { 948 "event": "fakeEvent", 949 "action": "AbortJob" 950 } 951 ] 952 } 953 }`) 954 err := json.Unmarshal(jsonData, &job) 955 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 956 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 957 gomega.Expect(err).To(gomega.HaveOccurred()) 958 }) 959 960 ginkgo.It("job validate check: invalid action when create", func() { 961 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 962 defer e2eutil.CleanupTestContext(ctx) 963 964 var job v1alpha1.Job 965 jsonData := []byte(`{ 966 "apiVersion": "batch.volcano.sh/v1alpha1", 967 "kind": "Job", 968 "metadata": { 969 "name": "test-job" 970 }, 971 "spec": { 972 "minAvailable": 1, 973 "tasks": [ 974 { 975 "replicas": 2, 976 "template": { 977 "spec": { 978 "containers": [ 979 { 980 "image": "nginx", 981 "imagePullPolicy": "IfNotPresent", 982 "name": "nginx", 983 "resources": { 984 "requests": { 985 "cpu": "1" 986 } 987 } 988 } 989 ], 990 "restartPolicy": "Never" 991 } 992 } 993 } 994 ], 995 "policies": [ 996 { 997 "event": "PodEvicted", 998 "action": "fakeAction" 999 } 1000 ] 1001 } 1002 }`) 1003 err := json.Unmarshal(jsonData, &job) 1004 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1005 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 1006 gomega.Expect(err).To(gomega.HaveOccurred()) 1007 }) 1008 1009 ginkgo.It("job validate check: zero exitCode when create", func() { 1010 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 1011 defer e2eutil.CleanupTestContext(ctx) 1012 1013 var job v1alpha1.Job 1014 jsonData := []byte(`{ 1015 "apiVersion": "batch.volcano.sh/v1alpha1", 1016 "kind": "Job", 1017 "metadata": { 1018 "name": "test-job" 1019 }, 1020 "spec": { 1021 "minAvailable": 1, 1022 "tasks": [ 1023 { 1024 "replicas": 2, 1025 "template": { 1026 "spec": { 1027 "containers": [ 1028 { 1029 "image": "nginx", 1030 "imagePullPolicy": "IfNotPresent", 1031 "name": "nginx", 1032 "resources": { 1033 "requests": { 1034 "cpu": "1" 1035 } 1036 } 1037 } 1038 ], 1039 "restartPolicy": "Never" 1040 } 1041 } 1042 } 1043 ], 1044 "policies": [ 1045 { 1046 "action": "AbortJob", 1047 "exitCode": 0 1048 } 1049 ] 1050 } 1051 }`) 1052 err := json.Unmarshal(jsonData, &job) 1053 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1054 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 1055 gomega.Expect(err).To(gomega.HaveOccurred()) 1056 }) 1057 1058 ginkgo.It("job validate check: both any event and other events exist when create", func() { 1059 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 1060 defer e2eutil.CleanupTestContext(ctx) 1061 1062 var job v1alpha1.Job 1063 jsonData := []byte(`{ 1064 "apiVersion": "batch.volcano.sh/v1alpha1", 1065 "kind": "Job", 1066 "metadata": { 1067 "name": "test-job" 1068 }, 1069 "spec": { 1070 "minAvailable": 1, 1071 "tasks": [ 1072 { 1073 "replicas": 2, 1074 "template": { 1075 "spec": { 1076 "containers": [ 1077 { 1078 "image": "nginx", 1079 "imagePullPolicy": "IfNotPresent", 1080 "name": "nginx", 1081 "resources": { 1082 "requests": { 1083 "cpu": "1" 1084 } 1085 } 1086 } 1087 ], 1088 "restartPolicy": "Never" 1089 } 1090 } 1091 } 1092 ], 1093 "policies": [ 1094 { 1095 "event": "*", 1096 "action": "AbortJob" 1097 }, 1098 { 1099 "event": "PodFailed", 1100 "action": "RestartJob" 1101 } 1102 ] 1103 } 1104 }`) 1105 err := json.Unmarshal(jsonData, &job) 1106 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1107 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 1108 gomega.Expect(err).To(gomega.HaveOccurred()) 1109 }) 1110 1111 ginkgo.It("job validate check: invalid volume mount when create", func() { 1112 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 1113 defer e2eutil.CleanupTestContext(ctx) 1114 1115 var job v1alpha1.Job 1116 jsonData := []byte(`{ 1117 "apiVersion": "batch.volcano.sh/v1alpha1", 1118 "kind": "Job", 1119 "metadata": { 1120 "name": "test-job" 1121 }, 1122 "spec": { 1123 "minAvailable": 1, 1124 "tasks": [ 1125 { 1126 "replicas": 2, 1127 "template": { 1128 "spec": { 1129 "containers": [ 1130 { 1131 "image": "nginx", 1132 "imagePullPolicy": "IfNotPresent", 1133 "name": "nginx", 1134 "resources": { 1135 "requests": { 1136 "cpu": "1" 1137 } 1138 } 1139 } 1140 ], 1141 "restartPolicy": "Never" 1142 } 1143 } 1144 } 1145 ], 1146 "volumes": [ 1147 { 1148 "mountPath": "" 1149 } 1150 ] 1151 } 1152 }`) 1153 err := json.Unmarshal(jsonData, &job) 1154 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1155 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 1156 gomega.Expect(err).To(gomega.HaveOccurred()) 1157 }) 1158 1159 ginkgo.It("job validate check: duplicate mount volume when create", func() { 1160 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 1161 defer e2eutil.CleanupTestContext(ctx) 1162 1163 var job v1alpha1.Job 1164 jsonData := []byte(`{ 1165 "apiVersion": "batch.volcano.sh/v1alpha1", 1166 "kind": "Job", 1167 "metadata": { 1168 "name": "test-job" 1169 }, 1170 "spec": { 1171 "minAvailable": 1, 1172 "tasks": [ 1173 { 1174 "replicas": 2, 1175 "template": { 1176 "spec": { 1177 "containers": [ 1178 { 1179 "image": "nginx", 1180 "imagePullPolicy": "IfNotPresent", 1181 "name": "nginx", 1182 "resources": { 1183 "requests": { 1184 "cpu": "1" 1185 } 1186 } 1187 } 1188 ], 1189 "restartPolicy": "Never" 1190 } 1191 } 1192 } 1193 ], 1194 "volumes": [ 1195 { 1196 "mountPath": "/var", 1197 "volumeClaimName": "pvc1" 1198 }, 1199 { 1200 "mountPath": "/var", 1201 "volumeClaimName": "pvc2" 1202 } 1203 ] 1204 } 1205 }`) 1206 err := json.Unmarshal(jsonData, &job) 1207 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1208 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 1209 gomega.Expect(err).To(gomega.HaveOccurred()) 1210 }) 1211 1212 ginkgo.It("job validate check: vloume without volumeClaimName and volumeClaim when create", func() { 1213 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 1214 defer e2eutil.CleanupTestContext(ctx) 1215 1216 var job v1alpha1.Job 1217 jsonData := []byte(`{ 1218 "apiVersion": "batch.volcano.sh/v1alpha1", 1219 "kind": "Job", 1220 "metadata": { 1221 "name": "test-job" 1222 }, 1223 "spec": { 1224 "minAvailable": 1, 1225 "tasks": [ 1226 { 1227 "replicas": 2, 1228 "template": { 1229 "spec": { 1230 "containers": [ 1231 { 1232 "image": "nginx", 1233 "imagePullPolicy": "IfNotPresent", 1234 "name": "nginx", 1235 "resources": { 1236 "requests": { 1237 "cpu": "1" 1238 } 1239 } 1240 } 1241 ], 1242 "restartPolicy": "Never" 1243 } 1244 } 1245 } 1246 ], 1247 "volumes": [ 1248 { 1249 "mountPath": "/var" 1250 } 1251 ] 1252 } 1253 }`) 1254 err := json.Unmarshal(jsonData, &job) 1255 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1256 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 1257 gomega.Expect(err).To(gomega.HaveOccurred()) 1258 }) 1259 1260 ginkgo.It("job validate check: vloume without volumeClaimName and volumeClaim when create", func() { 1261 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 1262 defer e2eutil.CleanupTestContext(ctx) 1263 1264 var job v1alpha1.Job 1265 jsonData := []byte(`{ 1266 "apiVersion": "batch.volcano.sh/v1alpha1", 1267 "kind": "Job", 1268 "metadata": { 1269 "name": "test-job" 1270 }, 1271 "spec": { 1272 "minAvailable": 1, 1273 "tasks": [ 1274 { 1275 "replicas": 2, 1276 "template": { 1277 "spec": { 1278 "containers": [ 1279 { 1280 "image": "nginx", 1281 "imagePullPolicy": "IfNotPresent", 1282 "name": "nginx", 1283 "resources": { 1284 "requests": { 1285 "cpu": "1" 1286 } 1287 } 1288 } 1289 ], 1290 "restartPolicy": "Never" 1291 } 1292 } 1293 } 1294 ], 1295 "volumes": [ 1296 { 1297 "mountPath": "/var" 1298 } 1299 ] 1300 } 1301 }`) 1302 err := json.Unmarshal(jsonData, &job) 1303 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1304 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 1305 gomega.Expect(err).To(gomega.HaveOccurred()) 1306 }) 1307 1308 ginkgo.It("job validate check: invalid queue when create", func() { 1309 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 1310 defer e2eutil.CleanupTestContext(ctx) 1311 1312 var job v1alpha1.Job 1313 jsonData := []byte(`{ 1314 "apiVersion": "batch.volcano.sh/v1alpha1", 1315 "kind": "Job", 1316 "metadata": { 1317 "name": "test-job" 1318 }, 1319 "spec": { 1320 "minAvailable": 1, 1321 "queue": "fakeQueue", 1322 "tasks": [ 1323 { 1324 "replicas": 2, 1325 "template": { 1326 "spec": { 1327 "containers": [ 1328 { 1329 "image": "nginx", 1330 "imagePullPolicy": "IfNotPresent", 1331 "name": "nginx", 1332 "resources": { 1333 "requests": { 1334 "cpu": "1" 1335 } 1336 } 1337 } 1338 ], 1339 "restartPolicy": "Never" 1340 } 1341 } 1342 } 1343 ] 1344 } 1345 }`) 1346 err := json.Unmarshal(jsonData, &job) 1347 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1348 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 1349 gomega.Expect(err).To(gomega.HaveOccurred()) 1350 }) 1351 1352 ginkgo.It("job validate check: create job with priviledged container", func() { 1353 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 1354 defer e2eutil.CleanupTestContext(ctx) 1355 1356 var job v1alpha1.Job 1357 jsonData := []byte(`{ 1358 "apiVersion": "batch.volcano.sh/v1alpha1", 1359 "kind": "Job", 1360 "metadata": { 1361 "name": "test-job" 1362 }, 1363 "spec": { 1364 "minAvailable": 1, 1365 "tasks": [ 1366 { 1367 "replicas": 2, 1368 "template": { 1369 "spec": { 1370 "containers": [ 1371 { 1372 "image": "nginx", 1373 "imagePullPolicy": "IfNotPresent", 1374 "name": "nginx", 1375 "resources": { 1376 "requests": { 1377 "cpu": "1" 1378 } 1379 }, 1380 "securityContext": { 1381 "privileged": true 1382 } 1383 } 1384 ], 1385 "restartPolicy": "Never" 1386 } 1387 } 1388 } 1389 ] 1390 } 1391 }`) 1392 err := json.Unmarshal(jsonData, &job) 1393 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1394 _, err = ctx.Vcclient.BatchV1alpha1().Jobs(ctx.Namespace).Create(context.TODO(), &job, v1.CreateOptions{}) 1395 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1396 }) 1397 1398 ginkgo.It("queue check: open queue can be deleted", func() { 1399 queueName := "deleted-open-queue" 1400 ctx := e2eutil.InitTestContext(e2eutil.Options{}) 1401 defer e2eutil.CleanupTestContext(ctx) 1402 1403 queue := &schedulingv1beta1.Queue{ 1404 ObjectMeta: metav1.ObjectMeta{ 1405 Name: queueName, 1406 }, 1407 Spec: schedulingv1beta1.QueueSpec{ 1408 Weight: 1, 1409 }, 1410 Status: schedulingv1beta1.QueueStatus{ 1411 State: schedulingv1beta1.QueueStateOpen, 1412 }, 1413 } 1414 1415 _, err := ctx.Vcclient.SchedulingV1beta1().Queues().Create(context.TODO(), queue, metav1.CreateOptions{}) 1416 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1417 err = e2eutil.WaitQueueStatus(func() (bool, error) { 1418 queue, err := ctx.Vcclient.SchedulingV1beta1().Queues().Get(context.TODO(), queue.Name, metav1.GetOptions{}) 1419 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1420 return queue.Status.State == schedulingv1beta1.QueueStateOpen, nil 1421 }) 1422 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1423 err = ctx.Vcclient.SchedulingV1beta1().Queues().Delete(context.TODO(), queue.Name, metav1.DeleteOptions{}) 1424 gomega.Expect(err).NotTo(gomega.HaveOccurred()) 1425 }) 1426 })