From 32aa740fd3fb8686c58673ef3916d0620fb37630 Mon Sep 17 00:00:00 2001 From: Timo Reimann Date: Sat, 21 May 2016 23:47:47 +0200 Subject: [PATCH] Show resources in pod descriptions by sorted names. Includes container and QoS resources. --- pkg/kubectl/describe.go | 14 ++++-- pkg/kubectl/describe_test.go | 28 +++++++++++ pkg/kubectl/sorted_resource_name_list.go | 23 +++++++++ pkg/kubectl/sorted_resource_name_list_test.go | 50 +++++++++++++++++++ pkg/kubelet/qos/util/qos.go | 9 ++-- 5 files changed, 116 insertions(+), 8 deletions(-) create mode 100644 pkg/kubectl/sorted_resource_name_list_test.go diff --git a/pkg/kubectl/describe.go b/pkg/kubectl/describe.go index d0201a197b5..0a3a7bb501a 100644 --- a/pkg/kubectl/describe.go +++ b/pkg/kubectl/describe.go @@ -842,21 +842,25 @@ func describeContainers(label string, containers []api.Container, containerStatu if len(resourceToQoS) > 0 { fmt.Fprintf(out, " QoS Tier:\n") } - for resource, qos := range resourceToQoS { + for _, resource := range SortedQoSResourceNames(resourceToQoS) { + qos := resourceToQoS[resource] fmt.Fprintf(out, " %s:\t%s\n", resource, qos) } - if len(container.Resources.Limits) > 0 { + resources := container.Resources + if len(resources.Limits) > 0 { fmt.Fprintf(out, " Limits:\n") } - for name, quantity := range container.Resources.Limits { + for _, name := range SortedResourceNames(resources.Limits) { + quantity := resources.Limits[name] fmt.Fprintf(out, " %s:\t%s\n", name, quantity.String()) } - if len(container.Resources.Requests) > 0 { + if len(resources.Requests) > 0 { fmt.Fprintf(out, " Requests:\n") } - for name, quantity := range container.Resources.Requests { + for _, name := range SortedResourceNames(resources.Requests) { + quantity := resources.Requests[name] fmt.Fprintf(out, " %s:\t%s\n", name, quantity.String()) } diff --git a/pkg/kubectl/describe_test.go b/pkg/kubectl/describe_test.go index ee8d99cf700..a9e0a1be0b2 100644 --- a/pkg/kubectl/describe_test.go +++ b/pkg/kubectl/describe_test.go @@ -238,6 +238,19 @@ func TestDescribeContainers(t *testing.T) { }, expectedElements: []string{"test", "State", "Waiting", "Ready", "True", "Restart Count", "7", "Image", "image", "time", "1000"}, }, + // QoS classes + { + container: api.Container{ + Name: "test", + Image: "image", + }, + status: api.ContainerStatus{ + Name: "test", + Ready: true, + RestartCount: 7, + }, + expectedElements: []string{"cpu", "BestEffort", "memory", "BestEffort"}, + }, // Using limits. { container: api.Container{ @@ -258,6 +271,21 @@ func TestDescribeContainers(t *testing.T) { }, expectedElements: []string{"cpu", "1k", "memory", "4G", "storage", "20G"}, }, + // Using requests. + { + container: api.Container{ + Name: "test", + Image: "image", + Resources: api.ResourceRequirements{ + Requests: api.ResourceList{ + api.ResourceName(api.ResourceCPU): resource.MustParse("1000"), + api.ResourceName(api.ResourceMemory): resource.MustParse("4G"), + api.ResourceName(api.ResourceStorage): resource.MustParse("20G"), + }, + }, + }, + expectedElements: []string{"cpu", "1k", "memory", "4G", "storage", "20G"}, + }, } for i, testCase := range testCases { diff --git a/pkg/kubectl/sorted_resource_name_list.go b/pkg/kubectl/sorted_resource_name_list.go index ffaa08ee46f..98c67344a3e 100644 --- a/pkg/kubectl/sorted_resource_name_list.go +++ b/pkg/kubectl/sorted_resource_name_list.go @@ -17,7 +17,10 @@ limitations under the License. package kubectl import ( + "sort" + "k8s.io/kubernetes/pkg/api" + qosutil "k8s.io/kubernetes/pkg/kubelet/qos/util" ) type SortableResourceNames []api.ResourceName @@ -34,6 +37,16 @@ func (list SortableResourceNames) Less(i, j int) bool { return list[i] < list[j] } +// SortedResourceNames returns the sorted resource names of a resource list. +func SortedResourceNames(list api.ResourceList) []api.ResourceName { + resources := make([]api.ResourceName, 0, len(list)) + for res := range list { + resources = append(resources, res) + } + sort.Sort(SortableResourceNames(resources)) + return resources +} + type SortableResourceQuotas []api.ResourceQuota func (list SortableResourceQuotas) Len() int { @@ -47,3 +60,13 @@ func (list SortableResourceQuotas) Swap(i, j int) { func (list SortableResourceQuotas) Less(i, j int) bool { return list[i].Name < list[j].Name } + +// SortedQoSResourceNames returns the sorted resource names of a QoS list. +func SortedQoSResourceNames(list qosutil.QoSList) []api.ResourceName { + resources := make([]api.ResourceName, 0, len(list)) + for res := range list { + resources = append(resources, res) + } + sort.Sort(SortableResourceNames(resources)) + return resources +} diff --git a/pkg/kubectl/sorted_resource_name_list_test.go b/pkg/kubectl/sorted_resource_name_list_test.go new file mode 100644 index 00000000000..c0e4855584f --- /dev/null +++ b/pkg/kubectl/sorted_resource_name_list_test.go @@ -0,0 +1,50 @@ +/* +Copyright 2016 The Kubernetes Authors All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package kubectl + +import ( + "reflect" + "sort" + "testing" + + "k8s.io/kubernetes/pkg/api" +) + +func TestSortableResourceNamesSorting(t *testing.T) { + want := SortableResourceNames{ + api.ResourceName(""), + api.ResourceName("42"), + api.ResourceName("bar"), + api.ResourceName("foo"), + api.ResourceName("foo"), + api.ResourceName("foobar"), + } + + in := SortableResourceNames{ + api.ResourceName("foo"), + api.ResourceName("42"), + api.ResourceName("foobar"), + api.ResourceName("foo"), + api.ResourceName("bar"), + api.ResourceName(""), + } + + sort.Sort(in) + if !reflect.DeepEqual(in, want) { + t.Errorf("got %v, want %v", in, want) + } +} diff --git a/pkg/kubelet/qos/util/qos.go b/pkg/kubelet/qos/util/qos.go index 7b8264e16c3..9d7a5786a3b 100644 --- a/pkg/kubelet/qos/util/qos.go +++ b/pkg/kubelet/qos/util/qos.go @@ -105,9 +105,12 @@ func GetPodQos(pod *api.Pod) string { return Burstable } -// GetQos returns a mapping of resource name to QoS class of a container -func GetQoS(container *api.Container) map[api.ResourceName]string { - resourceToQoS := map[api.ResourceName]string{} +// QoSList is a set of (resource name, QoS class) pairs. +type QoSList map[api.ResourceName]string + +// GetQoS returns a mapping of resource name to QoS class of a container +func GetQoS(container *api.Container) QoSList { + resourceToQoS := QoSList{} for resource := range allResources(container) { switch { case isResourceGuaranteed(container, resource):