...

Source file src/k8s.io/kubernetes/pkg/apis/core/v1/helper/qos/qos_test.go

Documentation: k8s.io/kubernetes/pkg/apis/core/v1/helper/qos

     1  /*
     2  Copyright 2016 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 qos
    18  
    19  import (
    20  	"testing"
    21  
    22  	v1 "k8s.io/api/core/v1"
    23  	"k8s.io/apimachinery/pkg/api/resource"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/kubernetes/pkg/apis/core"
    26  	"k8s.io/kubernetes/pkg/apis/core/helper/qos"
    27  	corev1 "k8s.io/kubernetes/pkg/apis/core/v1"
    28  )
    29  
    30  func TestComputePodQOS(t *testing.T) {
    31  	testCases := []struct {
    32  		pod      *v1.Pod
    33  		expected v1.PodQOSClass
    34  	}{
    35  		{
    36  			pod: newPod("guaranteed", []v1.Container{
    37  				newContainer("guaranteed", getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")),
    38  			}),
    39  			expected: v1.PodQOSGuaranteed,
    40  		},
    41  		{
    42  			pod: newPod("guaranteed-guaranteed", []v1.Container{
    43  				newContainer("guaranteed", getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")),
    44  				newContainer("guaranteed", getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")),
    45  			}),
    46  			expected: v1.PodQOSGuaranteed,
    47  		},
    48  		{
    49  			pod: newPod("best-effort-best-effort", []v1.Container{
    50  				newContainer("best-effort", getResourceList("", ""), getResourceList("", "")),
    51  				newContainer("best-effort", getResourceList("", ""), getResourceList("", "")),
    52  			}),
    53  			expected: v1.PodQOSBestEffort,
    54  		},
    55  		{
    56  			pod: newPod("best-effort", []v1.Container{
    57  				newContainer("best-effort", getResourceList("", ""), getResourceList("", "")),
    58  			}),
    59  			expected: v1.PodQOSBestEffort,
    60  		},
    61  		{
    62  			pod: newPod("best-effort-burstable", []v1.Container{
    63  				newContainer("best-effort", getResourceList("", ""), getResourceList("", "")),
    64  				newContainer("burstable", getResourceList("1", ""), getResourceList("2", "")),
    65  			}),
    66  			expected: v1.PodQOSBurstable,
    67  		},
    68  		{
    69  			pod: newPod("best-effort-guaranteed", []v1.Container{
    70  				newContainer("best-effort", getResourceList("", ""), getResourceList("", "")),
    71  				newContainer("guaranteed", getResourceList("10m", "100Mi"), getResourceList("10m", "100Mi")),
    72  			}),
    73  			expected: v1.PodQOSBurstable,
    74  		},
    75  		{
    76  			pod: newPod("burstable-cpu-guaranteed-memory", []v1.Container{
    77  				newContainer("burstable", getResourceList("", "100Mi"), getResourceList("", "100Mi")),
    78  			}),
    79  			expected: v1.PodQOSBurstable,
    80  		},
    81  		{
    82  			pod: newPod("burstable-no-limits", []v1.Container{
    83  				newContainer("burstable", getResourceList("100m", "100Mi"), getResourceList("", "")),
    84  			}),
    85  			expected: v1.PodQOSBurstable,
    86  		},
    87  		{
    88  			pod: newPod("burstable-guaranteed", []v1.Container{
    89  				newContainer("burstable", getResourceList("1", "100Mi"), getResourceList("2", "100Mi")),
    90  				newContainer("guaranteed", getResourceList("100m", "100Mi"), getResourceList("100m", "100Mi")),
    91  			}),
    92  			expected: v1.PodQOSBurstable,
    93  		},
    94  		{
    95  			pod: newPod("burstable-unbounded-but-requests-match-limits", []v1.Container{
    96  				newContainer("burstable", getResourceList("100m", "100Mi"), getResourceList("200m", "200Mi")),
    97  				newContainer("burstable-unbounded", getResourceList("100m", "100Mi"), getResourceList("", "")),
    98  			}),
    99  			expected: v1.PodQOSBurstable,
   100  		},
   101  		{
   102  			pod: newPod("burstable-1", []v1.Container{
   103  				newContainer("burstable", getResourceList("10m", "100Mi"), getResourceList("100m", "200Mi")),
   104  			}),
   105  			expected: v1.PodQOSBurstable,
   106  		},
   107  		{
   108  			pod: newPod("burstable-2", []v1.Container{
   109  				newContainer("burstable", getResourceList("0", "0"), getResourceList("100m", "200Mi")),
   110  			}),
   111  			expected: v1.PodQOSBurstable,
   112  		},
   113  		{
   114  			pod: newPod("best-effort-hugepages", []v1.Container{
   115  				newContainer("best-effort", addResource("hugepages-2Mi", "1Gi", getResourceList("0", "0")), addResource("hugepages-2Mi", "1Gi", getResourceList("0", "0"))),
   116  			}),
   117  			expected: v1.PodQOSBestEffort,
   118  		},
   119  		{
   120  			pod: newPodWithInitContainers("init-container",
   121  				[]v1.Container{
   122  					newContainer("best-effort", getResourceList("", ""), getResourceList("", "")),
   123  				},
   124  				[]v1.Container{
   125  					newContainer("burstable", getResourceList("10m", "100Mi"), getResourceList("100m", "200Mi")),
   126  				}),
   127  			expected: v1.PodQOSBurstable,
   128  		},
   129  	}
   130  	for id, testCase := range testCases {
   131  		if actual := ComputePodQOS(testCase.pod); testCase.expected != actual {
   132  			t.Errorf("[%d]: invalid qos pod %s, expected: %s, actual: %s", id, testCase.pod.Name, testCase.expected, actual)
   133  		}
   134  
   135  		// Convert v1.Pod to core.Pod, and then check against `core.helper.ComputePodQOS`.
   136  		pod := core.Pod{}
   137  		corev1.Convert_v1_Pod_To_core_Pod(testCase.pod, &pod, nil)
   138  
   139  		if actual := qos.ComputePodQOS(&pod); core.PodQOSClass(testCase.expected) != actual {
   140  			t.Errorf("[%d]: conversion invalid qos pod %s, expected: %s, actual: %s", id, testCase.pod.Name, testCase.expected, actual)
   141  		}
   142  	}
   143  }
   144  
   145  func getResourceList(cpu, memory string) v1.ResourceList {
   146  	res := v1.ResourceList{}
   147  	if cpu != "" {
   148  		res[v1.ResourceCPU] = resource.MustParse(cpu)
   149  	}
   150  	if memory != "" {
   151  		res[v1.ResourceMemory] = resource.MustParse(memory)
   152  	}
   153  	return res
   154  }
   155  
   156  func addResource(rName, value string, rl v1.ResourceList) v1.ResourceList {
   157  	rl[v1.ResourceName(rName)] = resource.MustParse(value)
   158  	return rl
   159  }
   160  
   161  func getResourceRequirements(requests, limits v1.ResourceList) v1.ResourceRequirements {
   162  	res := v1.ResourceRequirements{}
   163  	res.Requests = requests
   164  	res.Limits = limits
   165  	return res
   166  }
   167  
   168  func newContainer(name string, requests v1.ResourceList, limits v1.ResourceList) v1.Container {
   169  	return v1.Container{
   170  		Name:      name,
   171  		Resources: getResourceRequirements(requests, limits),
   172  	}
   173  }
   174  
   175  func newPod(name string, containers []v1.Container) *v1.Pod {
   176  	return &v1.Pod{
   177  		ObjectMeta: metav1.ObjectMeta{
   178  			Name: name,
   179  		},
   180  		Spec: v1.PodSpec{
   181  			Containers: containers,
   182  		},
   183  	}
   184  }
   185  
   186  func newPodWithInitContainers(name string, containers []v1.Container, initContainers []v1.Container) *v1.Pod {
   187  	return &v1.Pod{
   188  		ObjectMeta: metav1.ObjectMeta{
   189  			Name: name,
   190  		},
   191  		Spec: v1.PodSpec{
   192  			Containers:     containers,
   193  			InitContainers: initContainers,
   194  		},
   195  	}
   196  }
   197  

View as plain text