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 }