...

Source file src/k8s.io/kubernetes/plugin/pkg/admission/extendedresourcetoleration/admission_test.go

Documentation: k8s.io/kubernetes/plugin/pkg/admission/extendedresourcetoleration

     1  /*
     2  Copyright 2017 The Kubernetes 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 extendedresourcetoleration
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"k8s.io/apimachinery/pkg/api/resource"
    24  	"k8s.io/apiserver/pkg/admission"
    25  	admissiontesting "k8s.io/apiserver/pkg/admission/testing"
    26  	"k8s.io/kubernetes/pkg/apis/core"
    27  	"k8s.io/kubernetes/pkg/apis/core/helper"
    28  )
    29  
    30  func TestAdmit(t *testing.T) {
    31  
    32  	plugin := admissiontesting.WithReinvocationTesting(t, newExtendedResourceToleration())
    33  
    34  	containerRequestingCPU := core.Container{
    35  		Resources: core.ResourceRequirements{
    36  			Requests: core.ResourceList{
    37  				core.ResourceCPU: *resource.NewQuantity(2, resource.DecimalSI),
    38  			},
    39  		},
    40  	}
    41  
    42  	containerRequestingMemory := core.Container{
    43  		Resources: core.ResourceRequirements{
    44  			Requests: core.ResourceList{
    45  				core.ResourceMemory: *resource.NewQuantity(2048, resource.DecimalSI),
    46  			},
    47  		},
    48  	}
    49  
    50  	extendedResource1 := "example.com/device-ek"
    51  	extendedResource2 := "example.com/device-do"
    52  
    53  	containerRequestingExtendedResource1 := core.Container{
    54  		Resources: core.ResourceRequirements{
    55  			Requests: core.ResourceList{
    56  				core.ResourceName(extendedResource1): *resource.NewQuantity(1, resource.DecimalSI),
    57  			},
    58  		},
    59  	}
    60  	containerRequestingExtendedResource2 := core.Container{
    61  		Resources: core.ResourceRequirements{
    62  			Requests: core.ResourceList{
    63  				core.ResourceName(extendedResource2): *resource.NewQuantity(2, resource.DecimalSI),
    64  			},
    65  		},
    66  	}
    67  
    68  	tests := []struct {
    69  		description  string
    70  		requestedPod core.Pod
    71  		expectedPod  core.Pod
    72  	}{
    73  		{
    74  			description: "empty pod without any extended resources, expect no change in tolerations",
    75  			requestedPod: core.Pod{
    76  				Spec: core.PodSpec{},
    77  			},
    78  			expectedPod: core.Pod{
    79  				Spec: core.PodSpec{},
    80  			},
    81  		},
    82  		{
    83  			description: "pod with container without any extended resources, expect no change in tolerations",
    84  			requestedPod: core.Pod{
    85  				Spec: core.PodSpec{
    86  					Containers: []core.Container{
    87  						containerRequestingCPU,
    88  					},
    89  				},
    90  			},
    91  			expectedPod: core.Pod{
    92  				Spec: core.PodSpec{
    93  					Containers: []core.Container{
    94  						containerRequestingCPU,
    95  					},
    96  				},
    97  			},
    98  		},
    99  		{
   100  			description: "pod with init container without any extended resources, expect no change in tolerations",
   101  			requestedPod: core.Pod{
   102  				Spec: core.PodSpec{
   103  					InitContainers: []core.Container{
   104  						containerRequestingMemory,
   105  					},
   106  				},
   107  			},
   108  			expectedPod: core.Pod{
   109  				Spec: core.PodSpec{
   110  					InitContainers: []core.Container{
   111  						containerRequestingMemory,
   112  					},
   113  				},
   114  			},
   115  		},
   116  		{
   117  			description: "pod with container with extended resource, expect toleration to be added",
   118  			requestedPod: core.Pod{
   119  				Spec: core.PodSpec{
   120  					Containers: []core.Container{
   121  						containerRequestingExtendedResource1,
   122  					},
   123  				},
   124  			},
   125  			expectedPod: core.Pod{
   126  				Spec: core.PodSpec{
   127  					Containers: []core.Container{
   128  						containerRequestingExtendedResource1,
   129  					},
   130  					Tolerations: []core.Toleration{
   131  						{
   132  							Key:      extendedResource1,
   133  							Operator: core.TolerationOpExists,
   134  							Effect:   core.TaintEffectNoSchedule,
   135  						},
   136  					},
   137  				},
   138  			},
   139  		},
   140  		{
   141  			description: "pod with init container with extended resource, expect toleration to be added",
   142  			requestedPod: core.Pod{
   143  				Spec: core.PodSpec{
   144  					InitContainers: []core.Container{
   145  						containerRequestingExtendedResource2,
   146  					},
   147  				},
   148  			},
   149  			expectedPod: core.Pod{
   150  				Spec: core.PodSpec{
   151  					InitContainers: []core.Container{
   152  						containerRequestingExtendedResource2,
   153  					},
   154  					Tolerations: []core.Toleration{
   155  						{
   156  							Key:      extendedResource2,
   157  							Operator: core.TolerationOpExists,
   158  							Effect:   core.TaintEffectNoSchedule,
   159  						},
   160  					},
   161  				},
   162  			},
   163  		},
   164  		{
   165  			description: "pod with existing tolerations and container with extended resource, expect existing tolerations to be preserved and new toleration to be added",
   166  			requestedPod: core.Pod{
   167  				Spec: core.PodSpec{
   168  					Containers: []core.Container{
   169  						containerRequestingCPU,
   170  						containerRequestingExtendedResource1,
   171  					},
   172  					Tolerations: []core.Toleration{
   173  						{
   174  							Key:      "foo",
   175  							Operator: core.TolerationOpEqual,
   176  							Value:    "bar",
   177  							Effect:   core.TaintEffectNoSchedule,
   178  						},
   179  					},
   180  				},
   181  			},
   182  			expectedPod: core.Pod{
   183  				Spec: core.PodSpec{
   184  					Containers: []core.Container{
   185  						containerRequestingCPU,
   186  						containerRequestingExtendedResource1,
   187  					},
   188  					Tolerations: []core.Toleration{
   189  						{
   190  							Key:      "foo",
   191  							Operator: core.TolerationOpEqual,
   192  							Value:    "bar",
   193  							Effect:   core.TaintEffectNoSchedule,
   194  						},
   195  						{
   196  							Key:      extendedResource1,
   197  							Operator: core.TolerationOpExists,
   198  							Effect:   core.TaintEffectNoSchedule,
   199  						},
   200  					},
   201  				},
   202  			},
   203  		},
   204  		{
   205  			description: "pod with multiple extended resources, expect multiple tolerations to be added",
   206  			requestedPod: core.Pod{
   207  				Spec: core.PodSpec{
   208  					Containers: []core.Container{
   209  						containerRequestingMemory,
   210  						containerRequestingExtendedResource1,
   211  					},
   212  					InitContainers: []core.Container{
   213  						containerRequestingCPU,
   214  						containerRequestingExtendedResource2,
   215  					},
   216  				},
   217  			},
   218  			expectedPod: core.Pod{
   219  				Spec: core.PodSpec{
   220  					Containers: []core.Container{
   221  						containerRequestingMemory,
   222  						containerRequestingExtendedResource1,
   223  					},
   224  					InitContainers: []core.Container{
   225  						containerRequestingCPU,
   226  						containerRequestingExtendedResource2,
   227  					},
   228  					Tolerations: []core.Toleration{
   229  						// Note the order, it's sorted by the Key
   230  						{
   231  							Key:      extendedResource2,
   232  							Operator: core.TolerationOpExists,
   233  							Effect:   core.TaintEffectNoSchedule,
   234  						},
   235  						{
   236  							Key:      extendedResource1,
   237  							Operator: core.TolerationOpExists,
   238  							Effect:   core.TaintEffectNoSchedule,
   239  						},
   240  					},
   241  				},
   242  			},
   243  		},
   244  		{
   245  			description: "pod with container requesting extended resource and existing correct toleration, expect no change in tolerations",
   246  			requestedPod: core.Pod{
   247  				Spec: core.PodSpec{
   248  					Containers: []core.Container{
   249  						containerRequestingCPU,
   250  						containerRequestingMemory,
   251  						containerRequestingExtendedResource1,
   252  					},
   253  					Tolerations: []core.Toleration{
   254  						{
   255  							Key:      extendedResource1,
   256  							Operator: core.TolerationOpExists,
   257  							Effect:   core.TaintEffectNoSchedule,
   258  						},
   259  					},
   260  				},
   261  			},
   262  			expectedPod: core.Pod{
   263  				Spec: core.PodSpec{
   264  					Containers: []core.Container{
   265  						containerRequestingCPU,
   266  						containerRequestingMemory,
   267  						containerRequestingExtendedResource1,
   268  					},
   269  					Tolerations: []core.Toleration{
   270  						{
   271  							Key:      extendedResource1,
   272  							Operator: core.TolerationOpExists,
   273  							Effect:   core.TaintEffectNoSchedule,
   274  						},
   275  					},
   276  				},
   277  			},
   278  		},
   279  		{
   280  			description: "pod with container requesting extended resource and existing toleration with the same key but different effect and value, expect existing tolerations to be preserved and new toleration to be added",
   281  			requestedPod: core.Pod{
   282  				Spec: core.PodSpec{
   283  					Containers: []core.Container{
   284  						containerRequestingCPU,
   285  						containerRequestingMemory,
   286  						containerRequestingExtendedResource1,
   287  					},
   288  					Tolerations: []core.Toleration{
   289  						{
   290  							Key:      extendedResource1,
   291  							Operator: core.TolerationOpEqual,
   292  							Value:    "foo",
   293  							Effect:   core.TaintEffectNoExecute,
   294  						},
   295  					},
   296  				},
   297  			},
   298  			expectedPod: core.Pod{
   299  				Spec: core.PodSpec{
   300  					Containers: []core.Container{
   301  						containerRequestingCPU,
   302  						containerRequestingMemory,
   303  						containerRequestingExtendedResource1,
   304  					},
   305  					Tolerations: []core.Toleration{
   306  						{
   307  							Key:      extendedResource1,
   308  							Operator: core.TolerationOpEqual,
   309  							Value:    "foo",
   310  							Effect:   core.TaintEffectNoExecute,
   311  						},
   312  						{
   313  							Key:      extendedResource1,
   314  							Operator: core.TolerationOpExists,
   315  							Effect:   core.TaintEffectNoSchedule,
   316  						},
   317  					},
   318  				},
   319  			},
   320  		},
   321  		{
   322  			description: "pod with wildcard toleration and container requesting extended resource, expect existing tolerations to be preserved and new toleration to be added",
   323  			requestedPod: core.Pod{
   324  				Spec: core.PodSpec{
   325  					Containers: []core.Container{
   326  						containerRequestingCPU,
   327  						containerRequestingMemory,
   328  						containerRequestingExtendedResource1,
   329  					},
   330  					Tolerations: []core.Toleration{
   331  						{
   332  							Operator: core.TolerationOpExists,
   333  						},
   334  					},
   335  				},
   336  			},
   337  			expectedPod: core.Pod{
   338  				Spec: core.PodSpec{
   339  					Containers: []core.Container{
   340  						containerRequestingCPU,
   341  						containerRequestingMemory,
   342  						containerRequestingExtendedResource1,
   343  					},
   344  					Tolerations: []core.Toleration{
   345  						{
   346  							Operator: core.TolerationOpExists,
   347  						},
   348  						{
   349  							Key:      extendedResource1,
   350  							Operator: core.TolerationOpExists,
   351  							Effect:   core.TaintEffectNoSchedule,
   352  						},
   353  					},
   354  				},
   355  			},
   356  		},
   357  	}
   358  	for i, test := range tests {
   359  		err := plugin.Admit(context.TODO(), admission.NewAttributesRecord(&test.requestedPod, nil, core.Kind("Pod").WithVersion("version"), "foo", "name", core.Resource("pods").WithVersion("version"), "", "ignored", nil, false, nil), nil)
   360  		if err != nil {
   361  			t.Errorf("[%d: %s] unexpected error %v for pod %+v", i, test.description, err, test.requestedPod)
   362  		}
   363  
   364  		if !helper.Semantic.DeepEqual(test.expectedPod.Spec.Tolerations, test.requestedPod.Spec.Tolerations) {
   365  			t.Errorf("[%d: %s] expected %#v got %#v", i, test.description, test.expectedPod.Spec.Tolerations, test.requestedPod.Spec.Tolerations)
   366  		}
   367  	}
   368  }
   369  
   370  func TestHandles(t *testing.T) {
   371  	plugin := newExtendedResourceToleration()
   372  	tests := map[admission.Operation]bool{
   373  		admission.Create:  true,
   374  		admission.Update:  true,
   375  		admission.Delete:  false,
   376  		admission.Connect: false,
   377  	}
   378  	for op, expected := range tests {
   379  		result := plugin.Handles(op)
   380  		if result != expected {
   381  			t.Errorf("Unexpected result for operation %s: %v\n", op, result)
   382  		}
   383  	}
   384  }
   385  

View as plain text