volcano.sh/volcano@v1.9.0/pkg/controllers/job/job_controller_plugins_test.go (about)

     1  /*
     2  Copyright 2019 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 job
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"testing"
    23  
    24  	v1 "k8s.io/api/core/v1"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  	"k8s.io/client-go/informers"
    27  	kubeclient "k8s.io/client-go/kubernetes/fake"
    28  
    29  	batch "volcano.sh/apis/pkg/apis/batch/v1alpha1"
    30  	volcanoclient "volcano.sh/apis/pkg/client/clientset/versioned/fake"
    31  	"volcano.sh/volcano/pkg/controllers/framework"
    32  )
    33  
    34  func newFakeController() *jobcontroller {
    35  	volcanoClientSet := volcanoclient.NewSimpleClientset()
    36  	kubeClientSet := kubeclient.NewSimpleClientset()
    37  
    38  	sharedInformers := informers.NewSharedInformerFactory(kubeClientSet, 0)
    39  
    40  	controller := &jobcontroller{}
    41  	opt := &framework.ControllerOption{
    42  		VolcanoClient:         volcanoClientSet,
    43  		KubeClient:            kubeClientSet,
    44  		SharedInformerFactory: sharedInformers,
    45  		WorkerNum:             3,
    46  	}
    47  
    48  	controller.Initialize(opt)
    49  
    50  	return controller
    51  }
    52  
    53  func TestPluginOnPodCreate(t *testing.T) {
    54  	namespace := "test"
    55  
    56  	testcases := []struct {
    57  		Name    string
    58  		Job     *batch.Job
    59  		Pod     *v1.Pod
    60  		Plugins []string
    61  		RetVal  error
    62  	}{
    63  		{
    64  			Name: "All Plugin",
    65  			Job: &batch.Job{
    66  				ObjectMeta: metav1.ObjectMeta{
    67  					Name:      "Job1",
    68  					Namespace: namespace,
    69  					UID:       "e7f18111-1cec-11ea-b688-fa163ec79500",
    70  				},
    71  			},
    72  			Pod:     buildPod(namespace, "pod1", v1.PodPending, nil),
    73  			Plugins: []string{"env", "svc", "ssh"},
    74  			RetVal:  nil,
    75  		},
    76  		{
    77  			Name: "Wrong Plugin",
    78  			Job: &batch.Job{
    79  				ObjectMeta: metav1.ObjectMeta{
    80  					Name: "Job1",
    81  					UID:  "e7f18111-1cec-11ea-b688-fa163ec79500",
    82  				},
    83  			},
    84  			Pod:     buildPod(namespace, "pod1", v1.PodPending, nil),
    85  			Plugins: []string{"new"},
    86  			RetVal:  fmt.Errorf("failed to get plugin %s", "new"),
    87  		},
    88  	}
    89  
    90  	for i, testcase := range testcases {
    91  
    92  		t.Run(testcase.Name, func(t *testing.T) {
    93  			fakeController := newFakeController()
    94  			jobPlugins := make(map[string][]string)
    95  
    96  			for _, plugin := range testcase.Plugins {
    97  				jobPlugins[plugin] = make([]string, 0)
    98  			}
    99  
   100  			testcase.Job.Spec.Plugins = jobPlugins
   101  
   102  			err := fakeController.pluginOnPodCreate(testcase.Job, testcase.Pod)
   103  			if testcase.RetVal != nil && err.Error() != testcase.RetVal.Error() {
   104  				t.Errorf("case %d (%s): expected: %v, got %v ", i, testcase.Name, testcase.RetVal, err)
   105  			}
   106  
   107  			for _, plugin := range testcase.Plugins {
   108  				if plugin == "env" {
   109  					for _, container := range testcase.Pod.Spec.Containers {
   110  						if len(container.Env) == 0 {
   111  							t.Errorf("case %d (%s): expected: Env Length not to be zero", i, testcase.Name)
   112  						}
   113  					}
   114  				}
   115  
   116  				if plugin == "svc" {
   117  					for _, container := range testcase.Pod.Spec.Containers {
   118  						if len(container.VolumeMounts) == 0 {
   119  							t.Errorf("case %d (%s): expected: VolumeMount Length not to be zero", i, testcase.Name)
   120  						}
   121  						exist := false
   122  						for _, volume := range container.VolumeMounts {
   123  							if volume.Name == fmt.Sprint(testcase.Job.Name, "-svc") {
   124  								exist = true
   125  							}
   126  						}
   127  						if !exist {
   128  							t.Errorf("case %d (%s): expected: VolumeMount not created", i, testcase.Name)
   129  						}
   130  					}
   131  				}
   132  
   133  				if plugin == "ssh" {
   134  					for _, container := range testcase.Pod.Spec.Containers {
   135  						if len(container.VolumeMounts) == 0 {
   136  							t.Errorf("case %d (%s): expected: VolumeMount Length not to be zero", i, testcase.Name)
   137  						}
   138  						exist := false
   139  						for _, volume := range container.VolumeMounts {
   140  							if volume.Name == fmt.Sprintf("%s-%s", testcase.Job.Name, "ssh") {
   141  								exist = true
   142  							}
   143  						}
   144  						if !exist {
   145  							t.Errorf("case %d (%s): expected: VolumeMount not created", i, testcase.Name)
   146  						}
   147  					}
   148  				}
   149  			}
   150  		})
   151  	}
   152  }
   153  
   154  func TestPluginOnJobAdd(t *testing.T) {
   155  	namespace := "test"
   156  
   157  	testcases := []struct {
   158  		Name    string
   159  		Job     *batch.Job
   160  		Plugins []string
   161  		RetVal  error
   162  	}{
   163  		{
   164  			Name: "Plugins",
   165  			Job: &batch.Job{
   166  				ObjectMeta: metav1.ObjectMeta{
   167  					Name:      "job1",
   168  					Namespace: namespace,
   169  					UID:       "e7f18111-1cec-11ea-b688-fa163ec79500",
   170  				},
   171  			},
   172  			Plugins: []string{"svc", "ssh", "env"},
   173  			RetVal:  nil,
   174  		},
   175  		{
   176  			Name: "Wrong Plugin",
   177  			Job: &batch.Job{
   178  				ObjectMeta: metav1.ObjectMeta{
   179  					Name: "Job1",
   180  					UID:  "e7f18111-1cec-11ea-b688-fa163ec79500",
   181  				},
   182  			},
   183  			Plugins: []string{"new"},
   184  			RetVal:  fmt.Errorf("failed to get plugin %s", "new"),
   185  		},
   186  	}
   187  
   188  	for i, testcase := range testcases {
   189  
   190  		t.Run(testcase.Name, func(t *testing.T) {
   191  			fakeController := newFakeController()
   192  			jobPlugins := make(map[string][]string)
   193  
   194  			for _, plugin := range testcase.Plugins {
   195  				jobPlugins[plugin] = make([]string, 0)
   196  			}
   197  
   198  			testcase.Job.Spec.Plugins = jobPlugins
   199  
   200  			err := fakeController.pluginOnJobAdd(testcase.Job)
   201  			if testcase.RetVal != nil && err.Error() != testcase.RetVal.Error() {
   202  				t.Errorf("case %d (%s): expected: %v, got %v ", i, testcase.Name, testcase.RetVal, err)
   203  			}
   204  
   205  			for _, plugin := range testcase.Plugins {
   206  
   207  				if plugin == "svc" {
   208  					_, err := fakeController.kubeClient.CoreV1().ConfigMaps(namespace).Get(context.TODO(), fmt.Sprint(testcase.Job.Name, "-svc"), metav1.GetOptions{})
   209  					if err != nil {
   210  						t.Errorf("Case %d (%s): expected: ConfigMap to be created, but not created because of error %s", i, testcase.Name, err.Error())
   211  					}
   212  
   213  					_, err = fakeController.kubeClient.CoreV1().Services(namespace).Get(context.TODO(), testcase.Job.Name, metav1.GetOptions{})
   214  					if err != nil {
   215  						t.Errorf("Case %d (%s): expected: Service to be created, but not created because of error %s", i, testcase.Name, err.Error())
   216  					}
   217  				}
   218  
   219  				if plugin == "ssh" {
   220  					_, err := fakeController.kubeClient.CoreV1().Secrets(namespace).Get(context.TODO(),
   221  						fmt.Sprintf("%s-%s", testcase.Job.Name, "ssh"), metav1.GetOptions{})
   222  					if err != nil {
   223  						t.Errorf("Case %d (%s): expected: Secret to be created, but not created because of error %s", i, testcase.Name, err.Error())
   224  					}
   225  				}
   226  
   227  				if plugin == "env" {
   228  					if testcase.Job.Status.ControlledResources["plugin-env"] == "" {
   229  						t.Errorf("Case %d (%s): expected: to find controlled resource, but not found because of error %s", i, testcase.Name, err.Error())
   230  					}
   231  				}
   232  			}
   233  		})
   234  	}
   235  }
   236  
   237  func TestPluginOnJobDelete(t *testing.T) {
   238  	namespace := "test"
   239  
   240  	testcases := []struct {
   241  		Name    string
   242  		Job     *batch.Job
   243  		Plugins []string
   244  		RetVal  error
   245  	}{
   246  		{
   247  			Name: "Plugins",
   248  			Job: &batch.Job{
   249  				ObjectMeta: metav1.ObjectMeta{
   250  					Name:      "job1",
   251  					Namespace: namespace,
   252  					UID:       "e7f18111-1cec-11ea-b688-fa163ec79500",
   253  				},
   254  			},
   255  			Plugins: []string{"svc", "ssh", "env"},
   256  			RetVal:  nil,
   257  		},
   258  		{
   259  			Name: "Wrong Plugin",
   260  			Job: &batch.Job{
   261  				ObjectMeta: metav1.ObjectMeta{
   262  					Name: "Job1",
   263  					UID:  "e7f18111-1cec-11ea-b688-fa163ec79500",
   264  				},
   265  			},
   266  			Plugins: []string{"new"},
   267  			RetVal:  fmt.Errorf("failed to get plugin %s", "new"),
   268  		},
   269  	}
   270  
   271  	for i, testcase := range testcases {
   272  
   273  		t.Run(testcase.Name, func(t *testing.T) {
   274  			fakeController := newFakeController()
   275  			jobPlugins := make(map[string][]string)
   276  
   277  			for _, plugin := range testcase.Plugins {
   278  				jobPlugins[plugin] = make([]string, 0)
   279  			}
   280  
   281  			testcase.Job.Spec.Plugins = jobPlugins
   282  
   283  			err := fakeController.pluginOnJobDelete(testcase.Job)
   284  			if testcase.RetVal != nil && err.Error() != testcase.RetVal.Error() {
   285  				t.Errorf("case %d (%s): expected: %v, got %v ", i, testcase.Name, testcase.RetVal, err)
   286  			}
   287  
   288  			for _, plugin := range testcase.Plugins {
   289  
   290  				if plugin == "svc" {
   291  					_, err := fakeController.kubeClient.CoreV1().ConfigMaps(namespace).Get(context.TODO(), fmt.Sprint(testcase.Job.Name, "-svc"), metav1.GetOptions{})
   292  					if err == nil {
   293  						t.Errorf("Case %d (%s): expected: ConfigMap to be deleted, but not deleted.", i, testcase.Name)
   294  					}
   295  
   296  					_, err = fakeController.kubeClient.CoreV1().Services(namespace).Get(context.TODO(), testcase.Job.Name, metav1.GetOptions{})
   297  					if err == nil {
   298  						t.Errorf("Case %d (%s): expected: Service to be deleted, but not deleted.", i, testcase.Name)
   299  					}
   300  				}
   301  
   302  				if plugin == "ssh" {
   303  					_, err := fakeController.kubeClient.CoreV1().Secrets(namespace).Get(context.TODO(),
   304  						fmt.Sprintf("%s-%s-%s", testcase.Job.Name, testcase.Job.UID, "ssh"), metav1.GetOptions{})
   305  					if err == nil {
   306  						t.Errorf("Case %d (%s): expected: secret to be deleted, but not deleted.", i, testcase.Name)
   307  					}
   308  				}
   309  			}
   310  		})
   311  	}
   312  }