volcano.sh/volcano@v1.9.0/pkg/webhooks/admission/pods/mutate/mutate_pod_test.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 mutate
    18  
    19  import (
    20  	"encoding/json"
    21  	"reflect"
    22  	"testing"
    23  
    24  	v1 "k8s.io/api/core/v1"
    25  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    26  
    27  	webconfig "volcano.sh/volcano/pkg/webhooks/config"
    28  )
    29  
    30  func TestMutatePods(t *testing.T) {
    31  	affinityJSONStr := `{"nodeAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key":"kubernetes.io/os","operator":"In","values":["linux"]}]}]}}}`
    32  	var affinity v1.Affinity
    33  	json.Unmarshal([]byte(affinityJSONStr), &affinity)
    34  
    35  	admissionConfigData := &webconfig.AdmissionConfiguration{
    36  		ResGroupsConfig: []webconfig.ResGroupConfig{
    37  			{
    38  				ResourceGroup: "management",
    39  				Object: webconfig.Object{
    40  					Key: "namespace",
    41  					Value: []string{
    42  						"mng-ns-1",
    43  						"mng-ns-2",
    44  					},
    45  				},
    46  				SchedulerName: "default-scheduler",
    47  				Tolerations: []v1.Toleration{
    48  					{
    49  						Key:      "mng-taint-1",
    50  						Operator: v1.TolerationOpExists,
    51  						Effect:   v1.TaintEffectNoSchedule,
    52  					},
    53  				},
    54  				Affinity: affinityJSONStr,
    55  				Labels: map[string]string{
    56  					"volcano.sh/nodetype": "management",
    57  				},
    58  			},
    59  			{
    60  				ResourceGroup: "cpu",
    61  				Object: webconfig.Object{
    62  					Key: "annotation",
    63  					Value: []string{
    64  						"volcano.sh/resource-group: cpu",
    65  					},
    66  				},
    67  				SchedulerName: "volcano",
    68  				Labels: map[string]string{
    69  					"volcano.sh/nodetype": "cpu",
    70  				},
    71  			},
    72  			{
    73  				ResourceGroup: "gpu",
    74  				SchedulerName: "volcano",
    75  				Labels: map[string]string{
    76  					"volcano.sh/nodetype": "gpu",
    77  				},
    78  			},
    79  		},
    80  	}
    81  
    82  	config.ConfigData = admissionConfigData
    83  
    84  	testCases := []struct {
    85  		Name   string
    86  		Pod    *v1.Pod
    87  		expect []patchOperation
    88  	}{
    89  		{
    90  			Name: "test-1",
    91  			Pod: &v1.Pod{
    92  				TypeMeta: metav1.TypeMeta{
    93  					APIVersion: "v1",
    94  					Kind:       "Pod",
    95  				},
    96  				ObjectMeta: metav1.ObjectMeta{
    97  					Namespace: "mng-ns-1",
    98  					Name:      "mng-pod",
    99  				},
   100  				Spec: v1.PodSpec{
   101  					SchedulerName: "default-scheduler",
   102  				},
   103  			},
   104  			expect: []patchOperation{
   105  				{
   106  					Op:   "add",
   107  					Path: "/spec/nodeSelector",
   108  					Value: map[string]string{
   109  						"volcano.sh/nodetype": "management",
   110  					},
   111  				},
   112  				{
   113  					Op:    "add",
   114  					Path:  "/spec/affinity",
   115  					Value: affinity,
   116  				},
   117  				{
   118  					Op:   "add",
   119  					Path: "/spec/tolerations",
   120  					Value: []v1.Toleration{
   121  						{
   122  							Key:      "mng-taint-1",
   123  							Operator: v1.TolerationOpExists,
   124  							Effect:   v1.TaintEffectNoSchedule,
   125  						},
   126  					},
   127  				},
   128  				{
   129  					Op:    "add",
   130  					Path:  "/spec/schedulerName",
   131  					Value: "default-scheduler",
   132  				},
   133  			},
   134  		},
   135  		{
   136  			Name: "test-2",
   137  			Pod: &v1.Pod{
   138  				TypeMeta: metav1.TypeMeta{
   139  					APIVersion: "v1",
   140  					Kind:       "Pod",
   141  				},
   142  				ObjectMeta: metav1.ObjectMeta{
   143  					Name: "cpu-pod",
   144  					Annotations: map[string]string{
   145  						"volcano.sh/resource-group": "cpu",
   146  					},
   147  				},
   148  			},
   149  			expect: []patchOperation{
   150  				{
   151  					Op:   "add",
   152  					Path: "/spec/nodeSelector",
   153  					Value: map[string]string{
   154  						"volcano.sh/nodetype": "cpu",
   155  					},
   156  				},
   157  				{
   158  					Op:    "add",
   159  					Path:  "/spec/schedulerName",
   160  					Value: "volcano",
   161  				},
   162  			},
   163  		},
   164  		{
   165  			Name: "test-3",
   166  			Pod: &v1.Pod{
   167  				TypeMeta: metav1.TypeMeta{
   168  					APIVersion: "v1",
   169  					Kind:       "Pod",
   170  				},
   171  				ObjectMeta: metav1.ObjectMeta{
   172  					Name: "gpu-pod",
   173  					Annotations: map[string]string{
   174  						"volcano.sh/resource-group": "gpu",
   175  					},
   176  				},
   177  			},
   178  			expect: []patchOperation{
   179  				{
   180  					Op:   "add",
   181  					Path: "/spec/nodeSelector",
   182  					Value: map[string]string{
   183  						"volcano.sh/nodetype": "gpu",
   184  					},
   185  				},
   186  				{
   187  					Op:    "add",
   188  					Path:  "/spec/schedulerName",
   189  					Value: "volcano",
   190  				},
   191  			},
   192  		},
   193  		{
   194  			Name: "test-4",
   195  			Pod: &v1.Pod{
   196  				TypeMeta: metav1.TypeMeta{
   197  					APIVersion: "v1",
   198  					Kind:       "Pod",
   199  				},
   200  				ObjectMeta: metav1.ObjectMeta{
   201  					Name: "normal-pod",
   202  				},
   203  			},
   204  			expect: nil,
   205  		},
   206  	}
   207  
   208  	for _, testCase := range testCases {
   209  		t.Run(testCase.Name, func(t *testing.T) {
   210  			patchBytes, _ := createPatch(testCase.Pod)
   211  			expectBytes, _ := json.Marshal(testCase.expect)
   212  			if !reflect.DeepEqual(patchBytes, expectBytes) {
   213  				t.Errorf("Test case '%s' failed, expect: %v, got: %v", testCase.Name,
   214  					expectBytes, patchBytes)
   215  			}
   216  		})
   217  	}
   218  }