...

Source file src/k8s.io/kubernetes/pkg/apis/node/validation/validation_test.go

Documentation: k8s.io/kubernetes/pkg/apis/node/validation

     1  /*
     2  Copyright 2018 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 validation
    18  
    19  import (
    20  	"testing"
    21  
    22  	"k8s.io/apimachinery/pkg/api/resource"
    23  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    24  	"k8s.io/kubernetes/pkg/apis/core"
    25  	"k8s.io/kubernetes/pkg/apis/node"
    26  	utilpointer "k8s.io/utils/pointer"
    27  
    28  	"github.com/stretchr/testify/assert"
    29  )
    30  
    31  func TestValidateRuntimeClass(t *testing.T) {
    32  	tests := []struct {
    33  		name        string
    34  		rc          node.RuntimeClass
    35  		expectError bool
    36  	}{{
    37  		name:        "invalid name",
    38  		expectError: true,
    39  		rc: node.RuntimeClass{
    40  			ObjectMeta: metav1.ObjectMeta{Name: "&!@#"},
    41  			Handler:    "foo",
    42  		},
    43  	}, {
    44  		name:        "invalid Handler name",
    45  		expectError: true,
    46  		rc: node.RuntimeClass{
    47  			ObjectMeta: metav1.ObjectMeta{Name: "foo"},
    48  			Handler:    "&@#$",
    49  		},
    50  	}, {
    51  		name:        "invalid empty RuntimeClass",
    52  		expectError: true,
    53  		rc: node.RuntimeClass{
    54  			ObjectMeta: metav1.ObjectMeta{Name: "empty"},
    55  		},
    56  	}, {
    57  		name:        "valid Handler",
    58  		expectError: false,
    59  		rc: node.RuntimeClass{
    60  			ObjectMeta: metav1.ObjectMeta{Name: "foo"},
    61  			Handler:    "bar-baz",
    62  		},
    63  	}}
    64  
    65  	for _, test := range tests {
    66  		t.Run(test.name, func(t *testing.T) {
    67  			errs := ValidateRuntimeClass(&test.rc)
    68  			if test.expectError {
    69  				assert.NotEmpty(t, errs)
    70  			} else {
    71  				assert.Empty(t, errs)
    72  			}
    73  		})
    74  	}
    75  }
    76  
    77  func TestValidateRuntimeUpdate(t *testing.T) {
    78  	old := node.RuntimeClass{
    79  		ObjectMeta: metav1.ObjectMeta{Name: "foo"},
    80  		Handler:    "bar",
    81  	}
    82  	tests := []struct {
    83  		name        string
    84  		expectError bool
    85  		old, new    node.RuntimeClass
    86  	}{{
    87  		name: "valid metadata update",
    88  		old:  old,
    89  		new: node.RuntimeClass{
    90  			ObjectMeta: metav1.ObjectMeta{
    91  				Name:   "foo",
    92  				Labels: map[string]string{"foo": "bar"},
    93  			},
    94  			Handler: "bar",
    95  		},
    96  	}, {
    97  		name:        "invalid metadata update",
    98  		expectError: true,
    99  		old:         old,
   100  		new: node.RuntimeClass{
   101  			ObjectMeta: metav1.ObjectMeta{
   102  				Name:      "empty",
   103  				Namespace: "somethingelse", // immutable
   104  			},
   105  			Handler: "bar",
   106  		},
   107  	}, {
   108  		name:        "invalid Handler update",
   109  		expectError: true,
   110  		old:         old,
   111  		new: node.RuntimeClass{
   112  			ObjectMeta: metav1.ObjectMeta{Name: "foo"},
   113  			Handler:    "somethingelse",
   114  		},
   115  	}}
   116  
   117  	for _, test := range tests {
   118  		t.Run(test.name, func(t *testing.T) {
   119  			// So we don't need to write it in every test case...
   120  			test.old.ObjectMeta.ResourceVersion = "1"
   121  			test.new.ObjectMeta.ResourceVersion = "1"
   122  
   123  			errs := ValidateRuntimeClassUpdate(&test.new, &test.old)
   124  			if test.expectError {
   125  				assert.NotEmpty(t, errs)
   126  			} else {
   127  				assert.Empty(t, errs)
   128  			}
   129  		})
   130  	}
   131  }
   132  
   133  func TestValidateOverhead(t *testing.T) {
   134  	successCase := []struct {
   135  		Name     string
   136  		overhead *node.Overhead
   137  	}{{
   138  		Name: "Overhead with valid cpu and memory resources",
   139  		overhead: &node.Overhead{
   140  			PodFixed: core.ResourceList{
   141  				core.ResourceName(core.ResourceCPU):    resource.MustParse("10"),
   142  				core.ResourceName(core.ResourceMemory): resource.MustParse("10G"),
   143  			},
   144  		},
   145  	}}
   146  
   147  	for _, tc := range successCase {
   148  		rc := &node.RuntimeClass{
   149  			ObjectMeta: metav1.ObjectMeta{Name: "foo"},
   150  			Handler:    "bar",
   151  			Overhead:   tc.overhead,
   152  		}
   153  		if errs := ValidateRuntimeClass(rc); len(errs) != 0 {
   154  			t.Errorf("%q unexpected error: %v", tc.Name, errs)
   155  		}
   156  	}
   157  
   158  	errorCase := []struct {
   159  		Name     string
   160  		overhead *node.Overhead
   161  	}{{
   162  		Name: "Invalid Resources",
   163  		overhead: &node.Overhead{
   164  			PodFixed: core.ResourceList{
   165  				core.ResourceName("my.org"): resource.MustParse("10m"),
   166  			},
   167  		},
   168  	}}
   169  	for _, tc := range errorCase {
   170  		rc := &node.RuntimeClass{
   171  			ObjectMeta: metav1.ObjectMeta{Name: "foo"},
   172  			Handler:    "bar",
   173  			Overhead:   tc.overhead,
   174  		}
   175  		if errs := ValidateRuntimeClass(rc); len(errs) == 0 {
   176  			t.Errorf("%q expected error", tc.Name)
   177  		}
   178  	}
   179  }
   180  
   181  func TestValidateScheduling(t *testing.T) {
   182  	tests := []struct {
   183  		name       string
   184  		scheduling *node.Scheduling
   185  		expectErrs int
   186  	}{{
   187  		name: "valid scheduling",
   188  		scheduling: &node.Scheduling{
   189  			NodeSelector: map[string]string{"valid": "yes"},
   190  			Tolerations: []core.Toleration{{
   191  				Key:      "valid",
   192  				Operator: core.TolerationOpExists,
   193  				Effect:   core.TaintEffectNoSchedule,
   194  			}},
   195  		},
   196  	}, {
   197  		name:       "empty scheduling",
   198  		scheduling: &node.Scheduling{},
   199  	}, {
   200  		name: "invalid nodeSelector",
   201  		scheduling: &node.Scheduling{
   202  			NodeSelector: map[string]string{"not a valid key!!!": "nope"},
   203  		},
   204  		expectErrs: 1,
   205  	}, {
   206  		name: "invalid toleration",
   207  		scheduling: &node.Scheduling{
   208  			Tolerations: []core.Toleration{{
   209  				Key:      "valid",
   210  				Operator: core.TolerationOpExists,
   211  				Effect:   core.TaintEffectNoSchedule,
   212  			}, {
   213  				Key:      "not a valid key!!!",
   214  				Operator: core.TolerationOpExists,
   215  				Effect:   core.TaintEffectNoSchedule,
   216  			}},
   217  		},
   218  		expectErrs: 1,
   219  	}, {
   220  		name: "duplicate tolerations",
   221  		scheduling: &node.Scheduling{
   222  			Tolerations: []core.Toleration{{
   223  				Key:               "valid",
   224  				Operator:          core.TolerationOpExists,
   225  				Effect:            core.TaintEffectNoExecute,
   226  				TolerationSeconds: utilpointer.Int64(5),
   227  			}, {
   228  				Key:               "valid",
   229  				Operator:          core.TolerationOpExists,
   230  				Effect:            core.TaintEffectNoExecute,
   231  				TolerationSeconds: utilpointer.Int64(10),
   232  			}},
   233  		},
   234  		expectErrs: 1,
   235  	}, {
   236  		name: "invalid scheduling",
   237  		scheduling: &node.Scheduling{
   238  			NodeSelector: map[string]string{"not a valid key!!!": "nope"},
   239  			Tolerations: []core.Toleration{{
   240  				Key:      "valid",
   241  				Operator: core.TolerationOpExists,
   242  				Effect:   core.TaintEffectNoSchedule,
   243  			}, {
   244  				Key:      "not a valid toleration key!!!",
   245  				Operator: core.TolerationOpExists,
   246  				Effect:   core.TaintEffectNoSchedule,
   247  			}},
   248  		},
   249  		expectErrs: 2,
   250  	}}
   251  
   252  	for _, test := range tests {
   253  		t.Run(test.name, func(t *testing.T) {
   254  			rc := &node.RuntimeClass{
   255  				ObjectMeta: metav1.ObjectMeta{Name: "foo"},
   256  				Handler:    "bar",
   257  				Scheduling: test.scheduling,
   258  			}
   259  			assert.Len(t, ValidateRuntimeClass(rc), test.expectErrs)
   260  		})
   261  	}
   262  }
   263  

View as plain text