diff --git a/staging/src/k8s.io/kubectl/pkg/describe/describe.go b/staging/src/k8s.io/kubectl/pkg/describe/describe.go index 1e6acd75e13..75b1662e074 100644 --- a/staging/src/k8s.io/kubectl/pkg/describe/describe.go +++ b/staging/src/k8s.io/kubectl/pkg/describe/describe.go @@ -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()) } } diff --git a/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go b/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go index 27930c0846e..946ece04b68 100644 --- a/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go +++ b/staging/src/k8s.io/kubectl/pkg/describe/describe_test.go @@ -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 {