From b29135ea8fe4b10c74a675110ec5f778828f0632 Mon Sep 17 00:00:00 2001 From: Janet Kuo Date: Thu, 9 Mar 2017 15:21:35 -0800 Subject: [PATCH] In 'kubectl describe', find controllers with ControllerRef, instead of showing the original creator --- hack/make-rules/test-cmd-util.sh | 12 ++++++++++-- pkg/printers/internalversion/BUILD | 1 + pkg/printers/internalversion/describe.go | 25 +++++++++++++++++++++--- test/e2e/kubectl.go | 3 ++- 4 files changed, 35 insertions(+), 6 deletions(-) diff --git a/hack/make-rules/test-cmd-util.sh b/hack/make-rules/test-cmd-util.sh index 3b6d275d0ef..64e22d8fb81 100644 --- a/hack/make-rules/test-cmd-util.sh +++ b/hack/make-rules/test-cmd-util.sh @@ -287,7 +287,7 @@ run_pod_tests() { kube::test::get_object_jsonpath_assert 'pod/valid-pod' "{$id_field}" 'valid-pod' kube::test::get_object_jsonpath_assert 'pods/valid-pod' "{$id_field}" 'valid-pod' # Describe command should print detailed information - kube::test::describe_object_assert pods 'valid-pod' "Name:" "Image:" "Node:" "Labels:" "Status:" "Controllers" + kube::test::describe_object_assert pods 'valid-pod' "Name:" "Image:" "Node:" "Labels:" "Status:" # Describe command should print events information by default kube::test::describe_object_events_assert pods 'valid-pod' # Describe command should not print events information when show-events=false @@ -295,7 +295,7 @@ run_pod_tests() { # Describe command should print events information when show-events=true kube::test::describe_object_events_assert pods 'valid-pod' true # Describe command (resource only) should print detailed information - kube::test::describe_resource_assert pods "Name:" "Image:" "Node:" "Labels:" "Status:" "Controllers" + kube::test::describe_resource_assert pods "Name:" "Image:" "Node:" "Labels:" "Status:" # Describe command should print events information by default kube::test::describe_resource_events_assert pods @@ -1083,6 +1083,8 @@ run_kubectl_run_tests() { kubectl run pi --generator=job/v1 "--image=$IMAGE_PERL" --restart=OnFailure -- perl -Mbignum=bpi -wle 'print bpi(20)' "${kube_flags[@]}" # Post-Condition: Job "pi" is created kube::test::get_object_assert jobs "{{range.items}}{{$id_field}}:{{end}}" 'pi:' + # Describe command (resource only) should print detailed information + kube::test::describe_resource_assert pods "Name:" "Image:" "Node:" "Labels:" "Status:" "Created By" # Clean up kubectl delete jobs pi "${kube_flags[@]}" # Post-condition: no pods exist. @@ -2375,6 +2377,10 @@ run_deployment_tests() { kube::test::if_has_string "${output_message}" 'extensions/v1beta1' output_message=$(kubectl get deployment.apps -o=jsonpath='{.items[0].apiVersion}' 2>&1 "${kube_flags[@]}") kube::test::if_has_string "${output_message}" 'apps/v1beta1' + # Describe command (resource only) should print detailed information + kube::test::describe_resource_assert rs "Name:" "Pod Template:" "Labels:" "Selector:" "Controlled By" "Replicas:" "Pods Status:" "Volumes:" + # Describe command (resource only) should print detailed information + kube::test::describe_resource_assert pods "Name:" "Image:" "Node:" "Labels:" "Status:" "Created By" "Controlled By" # Clean up kubectl delete deployment test-nginx-apps "${kube_flags[@]}" @@ -2555,6 +2561,8 @@ run_rs_tests() { kube::test::describe_resource_events_assert rs false # Describe command should print events information when show-events=true kube::test::describe_resource_events_assert rs true + # Describe command (resource only) should print detailed information + kube::test::describe_resource_assert pods "Name:" "Image:" "Node:" "Labels:" "Status:" "Created By" "Controlled By" ### Scale replica set frontend with current-replicas and replicas # Pre-condition: 3 replicas diff --git a/pkg/printers/internalversion/BUILD b/pkg/printers/internalversion/BUILD index 18e7dfa067d..51043503d12 100644 --- a/pkg/printers/internalversion/BUILD +++ b/pkg/printers/internalversion/BUILD @@ -78,6 +78,7 @@ go_library( "//pkg/client/clientset_generated/internalclientset:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/core/internalversion:go_default_library", "//pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion:go_default_library", + "//pkg/controller:go_default_library", "//pkg/controller/deployment/util:go_default_library", "//pkg/fieldpath:go_default_library", "//pkg/kubelet/qos:go_default_library", diff --git a/pkg/printers/internalversion/describe.go b/pkg/printers/internalversion/describe.go index 1be0c0f9906..57a563b76fd 100644 --- a/pkg/printers/internalversion/describe.go +++ b/pkg/printers/internalversion/describe.go @@ -62,6 +62,7 @@ import ( clientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion" extensionsclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/extensions/internalversion" + "k8s.io/kubernetes/pkg/controller" deploymentutil "k8s.io/kubernetes/pkg/controller/deployment/util" "k8s.io/kubernetes/pkg/fieldpath" "k8s.io/kubernetes/pkg/kubelet/qos" @@ -554,7 +555,12 @@ func describePod(pod *api.Pod, events *api.EventList) (string, error) { w.Write(LEVEL_0, "Message:\t%s\n", pod.Status.Message) } w.Write(LEVEL_0, "IP:\t%s\n", pod.Status.PodIP) - w.Write(LEVEL_0, "Controllers:\t%s\n", printControllers(pod.Annotations)) + if createdBy := printCreator(pod.Annotations); len(createdBy) > 0 { + w.Write(LEVEL_0, "Created By:\t%s\n", createdBy) + } + if controlledBy := printController(pod); len(controlledBy) > 0 { + w.Write(LEVEL_0, "Controlled By:\t%s\n", controlledBy) + } if len(pod.Spec.InitContainers) > 0 { describeContainers("Init Containers", pod.Spec.InitContainers, pod.Status.InitContainerStatuses, EnvValueRetriever(pod), w, "") @@ -583,7 +589,14 @@ func describePod(pod *api.Pod, events *api.EventList) (string, error) { }) } -func printControllers(annotation map[string]string) string { +func printController(controllee metav1.Object) string { + if controllerRef := controller.GetControllerOf(controllee); controllerRef != nil { + return fmt.Sprintf("%s/%s", controllerRef.Kind, controllerRef.Name) + } + return "" +} + +func printCreator(annotation map[string]string) string { value, ok := annotation[api.CreatedByAnnotation] if ok { var r api.SerializedReference @@ -592,7 +605,7 @@ func printControllers(annotation map[string]string) string { return fmt.Sprintf("%s/%s", r.Reference.Kind, r.Reference.Name) } } - return "" + return "" } func describeVolumes(volumes []api.Volume, w PrefixWriter, space string) { @@ -1357,6 +1370,9 @@ func describeReplicaSet(rs *extensions.ReplicaSet, events *api.EventList, runnin w.Write(LEVEL_0, "Selector:\t%s\n", metav1.FormatLabelSelector(rs.Spec.Selector)) printLabelsMultiline(w, "Labels", rs.Labels) printAnnotationsMultiline(w, "Annotations", rs.Annotations) + if controlledBy := printController(rs); len(controlledBy) > 0 { + w.Write(LEVEL_0, "Controlled By:\t%s\n", controlledBy) + } w.Write(LEVEL_0, "Replicas:\t%d current / %d desired\n", rs.Status.Replicas, rs.Spec.Replicas) w.Write(LEVEL_0, "Pods Status:\t") if getPodErr != nil { @@ -1400,6 +1416,9 @@ func describeJob(job *batch.Job, events *api.EventList) (string, error) { w.Write(LEVEL_0, "Selector:\t%s\n", selector) printLabelsMultiline(w, "Labels", job.Labels) printAnnotationsMultiline(w, "Annotations", job.Annotations) + if createdBy := printCreator(job.Annotations); len(createdBy) > 0 { + w.Write(LEVEL_0, "Created By:\t%s\n", createdBy) + } w.Write(LEVEL_0, "Parallelism:\t%d\n", *job.Spec.Parallelism) if job.Spec.Completions != nil { w.Write(LEVEL_0, "Completions:\t%d\n", *job.Spec.Completions) diff --git a/test/e2e/kubectl.go b/test/e2e/kubectl.go index c74d09be664..4cac24deffa 100644 --- a/test/e2e/kubectl.go +++ b/test/e2e/kubectl.go @@ -777,7 +777,8 @@ var _ = framework.KubeDescribe("Kubectl client", func() { {"Annotations:"}, {"Status:", "Running"}, {"IP:"}, - {"Controllers:", "ReplicationController/redis-master"}, + {"Created By:", "ReplicationController/redis-master"}, + {"Controlled By:", "ReplicationController/redis-master"}, {"Image:", redisImage}, {"State:", "Running"}, {"QoS Class:", "BestEffort"},