Adding support for pod level resources in kubectl

1. Add support for pod level resources in kubectl
2. Reuse the existing method to describe container resources and generalize it to describe both pod and container level resources

Kubernetes-commit: 502e0f55c43291af800e8633760d461343bd39b3
This commit is contained in:
ndixita 2024-10-24 21:13:54 +00:00 committed by Kubernetes Publisher
parent 2bb31e1a0f
commit 1f9df3421a
2 changed files with 80 additions and 7 deletions

View File

@ -838,6 +838,11 @@ func describePod(pod *corev1.Pod, events *corev1.EventList) (string, error) {
w.Write(LEVEL_0, "NominatedNodeName:\t%s\n", pod.Status.NominatedNodeName)
}
if pod.Spec.Resources != nil {
w.Write(LEVEL_0, "Resources:\n")
describeResources(pod.Spec.Resources, w, LEVEL_1)
}
if len(pod.Spec.InitContainers) > 0 {
describeContainers("Init Containers", pod.Spec.InitContainers, pod.Status.InitContainerStatuses, EnvValueRetriever(pod), w, "")
}
@ -1800,7 +1805,7 @@ func describeContainers(label string, containers []corev1.Container, containerSt
if ok {
describeContainerState(status, w)
}
describeContainerResource(container, w)
describeResources(&container.Resources, w, LEVEL_2)
describeContainerProbe(container, w)
if len(container.EnvFrom) > 0 {
describeContainerEnvFrom(container, resolverFn, w)
@ -1886,22 +1891,25 @@ func describeContainerCommand(container corev1.Container, w PrefixWriter) {
}
}
func describeContainerResource(container corev1.Container, w PrefixWriter) {
resources := container.Resources
func describeResources(resources *corev1.ResourceRequirements, w PrefixWriter, level int) {
if resources == nil {
return
}
if len(resources.Limits) > 0 {
w.Write(LEVEL_2, "Limits:\n")
w.Write(level, "Limits:\n")
}
for _, name := range SortedResourceNames(resources.Limits) {
quantity := resources.Limits[name]
w.Write(LEVEL_3, "%s:\t%s\n", name, quantity.String())
w.Write(level+1, "%s:\t%s\n", name, quantity.String())
}
if len(resources.Requests) > 0 {
w.Write(LEVEL_2, "Requests:\n")
w.Write(level, "Requests:\n")
}
for _, name := range SortedResourceNames(resources.Requests) {
quantity := resources.Requests[name]
w.Write(LEVEL_3, "%s:\t%s\n", name, quantity.String())
w.Write(level+1, "%s:\t%s\n", name, quantity.String())
}
}

View File

@ -1179,6 +1179,71 @@ func VerifyDatesInOrder(
}
}
func TestDescribeResources(t *testing.T) {
testCases := []struct {
resources *corev1.ResourceRequirements
expectedElements map[string]int
}{
{
resources: &corev1.ResourceRequirements{},
expectedElements: map[string]int{},
},
{
resources: &corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1000"),
corev1.ResourceMemory: resource.MustParse("100Mi"),
},
Limits: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1000"),
corev1.ResourceMemory: resource.MustParse("100Mi"),
},
},
expectedElements: map[string]int{"cpu": 2, "memory": 2, "Requests": 1, "Limits": 1, "1k": 2, "100Mi": 2},
},
{
resources: &corev1.ResourceRequirements{
Limits: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1000"),
corev1.ResourceMemory: resource.MustParse("100Mi"),
},
},
expectedElements: map[string]int{"cpu": 1, "memory": 1, "Limits": 1, "1k": 1, "100Mi": 1},
},
{
resources: &corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceCPU: resource.MustParse("1000"),
corev1.ResourceMemory: resource.MustParse("100Mi"),
},
},
expectedElements: map[string]int{"cpu": 1, "memory": 1, "Requests": 1, "1k": 1, "100Mi": 1},
},
}
for i, testCase := range testCases {
t.Run(fmt.Sprintf("%d", i), func(t *testing.T) {
out := new(bytes.Buffer)
writer := NewPrefixWriter(out)
describeResources(testCase.resources, writer, LEVEL_1)
output := out.String()
gotElements := make(map[string]int)
for key, val := range testCase.expectedElements {
count := strings.Count(output, key)
if count == 0 {
t.Errorf("expected to find %q in output: %q", val, output)
continue
}
gotElements[key] = count
}
if !reflect.DeepEqual(gotElements, testCase.expectedElements) {
t.Errorf("Expected %v, got %v in output string: %q", testCase.expectedElements, gotElements, output)
}
})
}
}
func TestDescribeContainers(t *testing.T) {
trueVal := true
testCases := []struct {