k8s.io/kubernetes@v1.29.3/pkg/kubelet/types/pod_update_test.go (about) 1 /* 2 Copyright 2014 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 types 18 19 import ( 20 "testing" 21 22 "github.com/stretchr/testify/assert" 23 "github.com/stretchr/testify/require" 24 v1 "k8s.io/api/core/v1" 25 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 26 "k8s.io/kubernetes/pkg/apis/scheduling" 27 ) 28 29 var ( 30 systemPriority = scheduling.SystemCriticalPriority 31 systemPriorityUpper = systemPriority + 1000 32 ) 33 34 // getTestPod generates a new instance of an empty test Pod 35 func getTestPod(annotations map[string]string, podPriority *int32, priorityClassName string) *v1.Pod { 36 pod := v1.Pod{ 37 TypeMeta: metav1.TypeMeta{ 38 Kind: "Pod", 39 APIVersion: "v1", 40 }, 41 ObjectMeta: metav1.ObjectMeta{ 42 Name: "foo", 43 Namespace: "default", 44 }, 45 } 46 // Set pod Priority in Spec if exists 47 if podPriority != nil { 48 pod.Spec = v1.PodSpec{ 49 Priority: podPriority, 50 } 51 } 52 pod.Spec.PriorityClassName = priorityClassName 53 // Set annotations if exists 54 if annotations != nil { 55 pod.Annotations = annotations 56 } 57 return &pod 58 } 59 60 func configSourceAnnotation(source string) map[string]string { 61 return map[string]string{ConfigSourceAnnotationKey: source} 62 } 63 64 func configMirrorAnnotation() map[string]string { 65 return map[string]string{ConfigMirrorAnnotationKey: "true"} 66 } 67 68 func TestGetValidatedSources(t *testing.T) { 69 tests := []struct { 70 name string 71 sources []string 72 errExpected bool 73 sourcesLen int 74 }{ 75 { 76 name: "empty source", 77 sources: []string{""}, 78 errExpected: false, 79 sourcesLen: 0, 80 }, 81 { 82 name: "file and apiserver source", 83 sources: []string{FileSource, ApiserverSource}, 84 errExpected: false, 85 sourcesLen: 2, 86 }, 87 { 88 name: "all source", 89 sources: []string{AllSource}, 90 errExpected: false, 91 sourcesLen: 3, 92 }, 93 { 94 name: "unknown source", 95 sources: []string{"unknown"}, 96 errExpected: true, 97 sourcesLen: 0, 98 }, 99 } 100 101 for _, test := range tests { 102 t.Run(test.name, func(t *testing.T) { 103 sources, err := GetValidatedSources(test.sources) 104 if test.errExpected { 105 assert.Error(t, err) 106 } else { 107 assert.NoError(t, err) 108 } 109 assert.Len(t, sources, test.sourcesLen) 110 }) 111 } 112 } 113 114 func TestGetPodSource(t *testing.T) { 115 tests := []struct { 116 name string 117 pod *v1.Pod 118 expected string 119 errExpected bool 120 }{ 121 { 122 name: "cannot get pod source", 123 pod: getTestPod(nil, nil, ""), 124 expected: "", 125 errExpected: true, 126 }, 127 { 128 name: "valid annotation returns the source", 129 pod: getTestPod(configSourceAnnotation("host-ipc-sources"), nil, ""), 130 expected: "host-ipc-sources", 131 errExpected: false, 132 }, 133 } 134 135 for _, test := range tests { 136 t.Run(test.name, func(t *testing.T) { 137 source, err := GetPodSource(test.pod) 138 if test.errExpected { 139 assert.Error(t, err) 140 } else { 141 assert.NoError(t, err) 142 } 143 assert.Equal(t, test.expected, source) 144 }) 145 } 146 } 147 148 func TestString(t *testing.T) { 149 tests := []struct { 150 sp SyncPodType 151 expected string 152 }{ 153 { 154 sp: SyncPodCreate, 155 expected: "create", 156 }, 157 { 158 sp: SyncPodUpdate, 159 expected: "update", 160 }, 161 { 162 sp: SyncPodSync, 163 expected: "sync", 164 }, 165 { 166 sp: SyncPodKill, 167 expected: "kill", 168 }, 169 { 170 sp: 50, 171 expected: "unknown", 172 }, 173 } 174 for _, test := range tests { 175 t.Run(test.expected, func(t *testing.T) { 176 syncPodString := test.sp.String() 177 assert.Equal(t, test.expected, syncPodString) 178 }) 179 } 180 } 181 182 func TestIsMirrorPod(t *testing.T) { 183 tests := []struct { 184 name string 185 pod *v1.Pod 186 expected bool 187 }{ 188 { 189 name: "mirror pod", 190 pod: getTestPod(configMirrorAnnotation(), nil, ""), 191 expected: true, 192 }, 193 { 194 name: "not a mirror pod", 195 pod: getTestPod(nil, nil, ""), 196 expected: false, 197 }, 198 } 199 for _, test := range tests { 200 t.Run(test.name, func(t *testing.T) { 201 isMirrorPod := IsMirrorPod(test.pod) 202 assert.Equal(t, test.expected, isMirrorPod) 203 }) 204 } 205 } 206 207 func TestIsStaticPod(t *testing.T) { 208 tests := []struct { 209 name string 210 pod *v1.Pod 211 expected bool 212 }{ 213 { 214 name: "static pod with file source", 215 pod: getTestPod(configSourceAnnotation(FileSource), nil, ""), 216 expected: true, 217 }, 218 { 219 name: "static pod with http source", 220 pod: getTestPod(configSourceAnnotation(HTTPSource), nil, ""), 221 expected: true, 222 }, 223 { 224 name: "static pod with api server source", 225 pod: getTestPod(configSourceAnnotation(ApiserverSource), nil, ""), 226 expected: false, 227 }, 228 } 229 230 for _, test := range tests { 231 t.Run(test.name, func(t *testing.T) { 232 isStaticPod := IsStaticPod(test.pod) 233 assert.Equal(t, test.expected, isStaticPod) 234 }) 235 } 236 } 237 238 func TestIsCriticalPod(t *testing.T) { 239 tests := []struct { 240 name string 241 pod *v1.Pod 242 expected bool 243 }{ 244 { 245 name: "critical pod with file source", 246 pod: getTestPod(configSourceAnnotation(FileSource), nil, ""), 247 expected: true, 248 }, 249 { 250 name: "critical pod with mirror annotation", 251 pod: getTestPod(configMirrorAnnotation(), nil, ""), 252 expected: true, 253 }, 254 { 255 name: "critical pod using system priority", 256 pod: getTestPod(nil, &systemPriority, ""), 257 expected: true, 258 }, 259 { 260 name: "critical pod using greater than system priority", 261 pod: getTestPod(nil, &systemPriorityUpper, ""), 262 expected: true, 263 }, 264 { 265 name: "not a critical pod with api server annotation", 266 pod: getTestPod(configSourceAnnotation(ApiserverSource), nil, ""), 267 expected: false, 268 }, 269 { 270 name: "not critical if not static, mirror or without a priority", 271 pod: getTestPod(nil, nil, ""), 272 expected: false, 273 }, 274 } 275 for _, test := range tests { 276 t.Run(test.name, func(t *testing.T) { 277 isCriticalPod := IsCriticalPod(test.pod) 278 assert.Equal(t, test.expected, isCriticalPod) 279 }) 280 } 281 } 282 283 func TestPreemptable(t *testing.T) { 284 tests := []struct { 285 name string 286 preemptor *v1.Pod 287 preemptee *v1.Pod 288 expected bool 289 }{ 290 { 291 name: "a critical preemptor pod preempts a non critical pod", 292 preemptor: getTestPod(configSourceAnnotation(FileSource), nil, ""), 293 preemptee: getTestPod(nil, nil, ""), 294 expected: true, 295 }, 296 { 297 name: "a preemptor pod with higher priority preempts a critical pod", 298 preemptor: getTestPod(configSourceAnnotation(FileSource), &systemPriorityUpper, ""), 299 preemptee: getTestPod(configSourceAnnotation(FileSource), &systemPriority, ""), 300 expected: true, 301 }, 302 { 303 name: "a not critical pod with higher priority preempts a critical pod", 304 preemptor: getTestPod(configSourceAnnotation(ApiserverSource), &systemPriorityUpper, ""), 305 preemptee: getTestPod(configSourceAnnotation(FileSource), &systemPriority, ""), 306 expected: true, 307 }, 308 { 309 name: "a critical pod with less priority do not preempts a critical pod", 310 preemptor: getTestPod(configSourceAnnotation(FileSource), &systemPriority, ""), 311 preemptee: getTestPod(configSourceAnnotation(FileSource), &systemPriorityUpper, ""), 312 expected: false, 313 }, 314 { 315 name: "a critical pod without priority do not preempts a critical pod without priority", 316 preemptor: getTestPod(configSourceAnnotation(FileSource), nil, ""), 317 preemptee: getTestPod(configSourceAnnotation(FileSource), nil, ""), 318 expected: false, 319 }, 320 { 321 name: "a critical pod with priority do not preempts a critical pod with the same priority", 322 preemptor: getTestPod(configSourceAnnotation(FileSource), &systemPriority, ""), 323 preemptee: getTestPod(configSourceAnnotation(FileSource), &systemPriority, ""), 324 expected: false, 325 }, 326 } 327 for _, test := range tests { 328 t.Run(test.name, func(t *testing.T) { 329 isPreemtable := Preemptable(test.preemptor, test.preemptee) 330 assert.Equal(t, test.expected, isPreemtable) 331 }) 332 } 333 } 334 335 func TestIsCriticalPodBasedOnPriority(t *testing.T) { 336 tests := []struct { 337 priority int32 338 name string 339 expected bool 340 }{ 341 { 342 name: "a system critical pod", 343 priority: systemPriority, 344 expected: true, 345 }, 346 { 347 name: "a non system critical pod", 348 priority: scheduling.HighestUserDefinablePriority, 349 expected: false, 350 }, 351 } 352 for _, test := range tests { 353 t.Run(test.name, func(t *testing.T) { 354 actual := IsCriticalPodBasedOnPriority(test.priority) 355 if actual != test.expected { 356 t.Errorf("IsCriticalPodBased on priority should have returned %v for test %v but got %v", test.expected, test.name, actual) 357 } 358 }) 359 } 360 } 361 362 func TestIsNodeCriticalPod(t *testing.T) { 363 tests := []struct { 364 name string 365 pod *v1.Pod 366 expected bool 367 }{ 368 { 369 name: "critical pod with file source and systemNodeCritical", 370 pod: getTestPod(configSourceAnnotation(FileSource), nil, scheduling.SystemNodeCritical), 371 expected: true, 372 }, 373 { 374 name: "critical pod with mirror annotation and systemNodeCritical", 375 pod: getTestPod(configMirrorAnnotation(), nil, scheduling.SystemNodeCritical), 376 expected: true, 377 }, 378 { 379 name: "critical pod using system priority and systemNodeCritical", 380 pod: getTestPod(nil, &systemPriority, scheduling.SystemNodeCritical), 381 expected: true, 382 }, 383 { 384 name: "critical pod using greater than system priority and systemNodeCritical", 385 pod: getTestPod(nil, &systemPriorityUpper, scheduling.SystemNodeCritical), 386 expected: true, 387 }, 388 { 389 name: "not a critical pod with api server annotation and systemNodeCritical", 390 pod: getTestPod(configSourceAnnotation(ApiserverSource), nil, scheduling.SystemNodeCritical), 391 expected: false, 392 }, 393 { 394 name: "not critical if not static, mirror or without a priority and systemNodeCritical", 395 pod: getTestPod(nil, nil, scheduling.SystemNodeCritical), 396 expected: false, 397 }, 398 { 399 name: "not critical if not static, mirror or without a priority", 400 pod: getTestPod(nil, nil, ""), 401 expected: false, 402 }, 403 } 404 for _, test := range tests { 405 t.Run(test.name, func(t *testing.T) { 406 isNodeCriticalPod := IsNodeCriticalPod(test.pod) 407 require.Equal(t, test.expected, isNodeCriticalPod) 408 }) 409 } 410 }