Merge pull request #26046 from timoreimann/stabilize-map-order-in-kubectl-describe

Automatic merge from submit-queue

Stabilize map order in kubectl describe

Refs #25251.

Add `SortedResourceNames()` methods to map type aliases in order to achieve stable output order for `kubectl` descriptors.

This affects QoS classes, resource limits, and resource requests.

A few remarks:

1. I couldn't find map usages for described fields other than the ones mentioned above. Then again, I failed to identify those programmatically/systematically. Pointers given, I'd be happy to cover any gaps within this PR or along additional ones.
1. It's somewhat difficult to deterministically test a function that brings reliable ordering to Go maps due to its randomizing nature. None of the possibilities I came up with (rely a "probabilistic testing" against repeatedly created maps, add complexity through additional interfaces) seemed very appealing to me, so I went with testing my `sort.Interface` implementation and the changed logic in `kubectl.describeContainers()`.
1. It's apparently not possible to implement a single function that sorts any map's keys generically in Go without producing lots of boilerplate: a `map[<key type>]interface{}` is different from any other map type and thus requires explicit iteration on the caller site to convert back and forth. Unfortunately, this makes it hard to completely avoid code/test duplication.

Please let me know what you think.
This commit is contained in:
k8s-merge-robot
2016-05-28 10:49:57 -07:00
5 changed files with 116 additions and 8 deletions

View File

@@ -847,21 +847,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())
}