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  }