Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cleanup kubectl describe code #43947

Merged
merged 1 commit into from
May 15, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 0 additions & 1 deletion pkg/printers/internalversion/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ go_library(
"//pkg/client/clientset_generated/clientset/typed/extensions/v1beta1:go_default_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",
Expand Down
214 changes: 94 additions & 120 deletions pkg/printers/internalversion/describe.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package internalversion

import (
"bytes"
"crypto/x509"
"encoding/json"
"fmt"
"io"
Expand Down Expand Up @@ -64,7 +65,6 @@ import (
extensionsclientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset/typed/extensions/v1beta1"
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"
Expand Down Expand Up @@ -851,13 +851,15 @@ func (d *PersistentVolumeDescriber) Describe(namespace, name string, describerSe
return "", err
}

storage := pv.Spec.Capacity[api.ResourceStorage]

var events *api.EventList
if describerSettings.ShowEvents {
events, _ = d.Core().Events(namespace).Search(api.Scheme, pv)
}

return describePersistentVolume(pv, events)
}

func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", pv.Name)
Expand All @@ -872,6 +874,7 @@ func (d *PersistentVolumeDescriber) Describe(namespace, name string, describerSe
}
w.Write(LEVEL_0, "Reclaim Policy:\t%v\n", pv.Spec.PersistentVolumeReclaimPolicy)
w.Write(LEVEL_0, "Access Modes:\t%s\n", helper.GetAccessModesAsString(pv.Spec.AccessModes))
storage := pv.Spec.Capacity[api.ResourceStorage]
w.Write(LEVEL_0, "Capacity:\t%s\n", storage.String())
w.Write(LEVEL_0, "Message:\t%s\n", pv.Status.Message)
w.Write(LEVEL_0, "Source:\n")
Expand Down Expand Up @@ -927,17 +930,12 @@ func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string, descri
return "", err
}

storage := pvc.Spec.Resources.Requests[api.ResourceStorage]
capacity := ""
accessModes := ""
if pvc.Spec.VolumeName != "" {
accessModes = helper.GetAccessModesAsString(pvc.Status.AccessModes)
storage = pvc.Status.Capacity[api.ResourceStorage]
capacity = storage.String()
}

events, _ := d.Core().Events(namespace).Search(api.Scheme, pvc)

return describePersistentVolumeClaim(pvc, events)
}

func describePersistentVolumeClaim(pvc *api.PersistentVolumeClaim, events *api.EventList) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", pvc.Name)
Expand All @@ -947,6 +945,14 @@ func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string, descri
w.Write(LEVEL_0, "Volume:\t%s\n", pvc.Spec.VolumeName)
printLabelsMultiline(w, "Labels", pvc.Labels)
printAnnotationsMultiline(w, "Annotations", pvc.Annotations)
storage := pvc.Spec.Resources.Requests[api.ResourceStorage]
capacity := ""
accessModes := ""
if pvc.Spec.VolumeName != "" {
accessModes = helper.GetAccessModesAsString(pvc.Status.AccessModes)
storage = pvc.Status.Capacity[api.ResourceStorage]
capacity = storage.String()
}
w.Write(LEVEL_0, "Capacity:\t%s\n", capacity)
w.Write(LEVEL_0, "Access Modes:\t%s\n", accessModes)
if events != nil {
Expand Down Expand Up @@ -2150,6 +2156,15 @@ func (p *StatefulSetDescriber) Describe(namespace, name string, describerSetting
return "", err
}

var events *api.EventList
if describerSettings.ShowEvents {
events, _ = p.client.Core().Events(namespace).Search(api.Scheme, ps)
}

return describeStatefulSet(ps, selector, events, running, waiting, succeeded, failed)
}

func describeStatefulSet(ps *apps.StatefulSet, selector labels.Selector, events *api.EventList, running, waiting, succeeded, failed int) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", ps.ObjectMeta.Name)
Expand All @@ -2162,12 +2177,10 @@ func (p *StatefulSetDescriber) Describe(namespace, name string, describerSetting
w.Write(LEVEL_0, "Pods Status:\t%d Running / %d Waiting / %d Succeeded / %d Failed\n", running, waiting, succeeded, failed)
DescribePodTemplate(&ps.Spec.Template, w)
describeVolumeClaimTemplates(ps.Spec.VolumeClaimTemplates, w)
if describerSettings.ShowEvents {
events, _ := p.client.Core().Events(namespace).Search(api.Scheme, ps)
if events != nil {
DescribeEvents(events, w)
}
if events != nil {
DescribeEvents(events, w)
}

return nil
})
}
Expand All @@ -2191,6 +2204,15 @@ func (p *CertificateSigningRequestDescriber) Describe(namespace, name string, de
return "", err
}

var events *api.EventList
if describerSettings.ShowEvents {
events, _ = p.client.Core().Events(namespace).Search(api.Scheme, csr)
}

return describeCertificateSigningRequest(csr, cr, status, events)
}

func describeCertificateSigningRequest(csr *certificates.CertificateSigningRequest, cr *x509.CertificateRequest, status string, events *api.EventList) (string, error) {
printListHelper := func(w PrefixWriter, prefix, name string, values []string) {
if len(values) == 0 {
return
Expand Down Expand Up @@ -2231,12 +2253,10 @@ func (p *CertificateSigningRequestDescriber) Describe(namespace, name string, de
printListHelper(w, "\t", "IP Addresses", ipaddrs)
}

if describerSettings.ShowEvents {
events, _ := p.client.Core().Events(namespace).Search(api.Scheme, csr)
if events != nil {
DescribeEvents(events, w)
}
if events != nil {
DescribeEvents(events, w)
}

return nil
})
}
Expand All @@ -2251,6 +2271,16 @@ func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string, desc
if err != nil {
return "", err
}

var events *api.EventList
if describerSettings.ShowEvents {
events, _ = d.client.Core().Events(namespace).Search(api.Scheme, hpa)
}

return describeHorizontalPodAutoscaler(hpa, events, d)
}

func describeHorizontalPodAutoscaler(hpa *autoscaling.HorizontalPodAutoscaler, events *api.EventList, d *HorizontalPodAutoscalerDescriber) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", hpa.Name)
Expand Down Expand Up @@ -2318,12 +2348,10 @@ func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string, desc
}
}

if describerSettings.ShowEvents {
events, _ := d.client.Core().Events(namespace).Search(api.Scheme, hpa)
if events != nil {
DescribeEvents(events, w)
}
if events != nil {
DescribeEvents(events, w)
}

return nil
})
}
Expand Down Expand Up @@ -2369,20 +2397,6 @@ func describeNodeResource(nodeNonTerminatedPodsList *api.PodList, node *api.Node
return nil
}

func filterTerminatedPods(pods []*api.Pod) []*api.Pod {
if len(pods) == 0 {
return pods
}
result := []*api.Pod{}
for _, pod := range pods {
if pod.Status.Phase == api.PodSucceeded || pod.Status.Phase == api.PodFailed {
continue
}
result = append(result, pod)
}
return result
}

func getPodsTotalRequestsAndLimits(podList *api.PodList) (reqs map[api.ResourceName]resource.Quantity, limits map[api.ResourceName]resource.Quantity, err error) {
reqs, limits = map[api.ResourceName]resource.Quantity{}, map[api.ResourceName]resource.Quantity{}
for _, pod := range podList.Items {
Expand Down Expand Up @@ -2450,6 +2464,16 @@ func (dd *DeploymentDescriber) Describe(namespace, name string, describerSetting
if err := api.Scheme.Convert(d, internalDeployment, extensions.SchemeGroupVersion); err != nil {
return "", err
}

var events *api.EventList
if describerSettings.ShowEvents {
events, _ = dd.Core().Events(namespace).Search(api.Scheme, d)
}

return describeDeployment(d, selector, internalDeployment, events, dd)
}

func describeDeployment(d *versionedextension.Deployment, selector labels.Selector, internalDeployment *extensions.Deployment, events *api.EventList, dd *DeploymentDescriber) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", d.ObjectMeta.Name)
Expand Down Expand Up @@ -2486,58 +2510,14 @@ func (dd *DeploymentDescriber) Describe(namespace, name string, describerSetting
if len(overlapWith) > 0 {
w.Write(LEVEL_0, "!!!WARNING!!! This deployment has overlapping label selector with deployment %q and won't behave as expected. Please fix it before continuing.\n", overlapWith)
}
if describerSettings.ShowEvents {
events, err := dd.Core().Events(namespace).Search(api.Scheme, d)
if err == nil && events != nil {
DescribeEvents(events, w)
}
if events != nil {
DescribeEvents(events, w)
}

return nil
})
}

// Get all daemon set whose selectors would match a given set of labels.
// TODO: Move this to pkg/client and ideally implement it server-side (instead
// of getting all DS's and searching through them manually).
// TODO: write an interface for controllers and fuse getReplicationControllersForLabels
// and getDaemonSetsForLabels.
func getDaemonSetsForLabels(c extensionsclient.DaemonSetInterface, labelsToMatch labels.Labels) ([]extensions.DaemonSet, error) {
// Get all daemon sets
// TODO: this needs a namespace scope as argument
dss, err := c.List(metav1.ListOptions{})
if err != nil {
return nil, fmt.Errorf("error getting daemon set: %v", err)
}

// Find the ones that match labelsToMatch.
var matchingDaemonSets []extensions.DaemonSet
for _, ds := range dss.Items {
selector, err := metav1.LabelSelectorAsSelector(ds.Spec.Selector)
if err != nil {
// this should never happen if the DaemonSet passed validation
return nil, err
}
if selector.Matches(labelsToMatch) {
matchingDaemonSets = append(matchingDaemonSets, ds)
}
}
return matchingDaemonSets, nil
}

func printReplicationControllersByLabels(matchingRCs []*api.ReplicationController) string {
// Format the matching RC's into strings.
rcStrings := make([]string, 0, len(matchingRCs))
for _, controller := range matchingRCs {
rcStrings = append(rcStrings, fmt.Sprintf("%s (%d/%d replicas created)", controller.Name, controller.Status.Replicas, controller.Spec.Replicas))
}

list := strings.Join(rcStrings, ", ")
if list == "" {
return "<none>"
}
return list
}

func printReplicaSetsByLabels(matchingRSs []*versionedextension.ReplicaSet) string {
// Format the matching ReplicaSets into strings.
rsStrings := make([]string, 0, len(matchingRSs))
Expand Down Expand Up @@ -2689,22 +2669,27 @@ func (s *StorageClassDescriber) Describe(namespace, name string, describerSettin
if err != nil {
return "", err
}

var events *api.EventList
if describerSettings.ShowEvents {
events, _ = s.Core().Events(namespace).Search(api.Scheme, sc)
}

return describeStorageClass(sc, events)
}

func describeStorageClass(sc *storage.StorageClass, events *api.EventList) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", sc.Name)
w.Write(LEVEL_0, "IsDefaultClass:\t%s\n", storageutil.IsDefaultAnnotationText(sc.ObjectMeta))
w.Write(LEVEL_0, "Annotations:\t%s\n", labels.FormatLabels(sc.Annotations))
w.Write(LEVEL_0, "Provisioner:\t%s\n", sc.Provisioner)
w.Write(LEVEL_0, "Parameters:\t%s\n", labels.FormatLabels(sc.Parameters))
if describerSettings.ShowEvents {
events, err := s.Core().Events(namespace).Search(api.Scheme, sc)
if err != nil {
return err
}
if events != nil {
DescribeEvents(events, w)
}
if events != nil {
DescribeEvents(events, w)
}

return nil
})
}
Expand All @@ -2718,6 +2703,16 @@ func (p *PodDisruptionBudgetDescriber) Describe(namespace, name string, describe
if err != nil {
return "", err
}

var events *api.EventList
if describerSettings.ShowEvents {
events, _ = p.Core().Events(namespace).Search(api.Scheme, pdb)
}

return describePodDisruptionBudget(pdb, events)
}

func describePodDisruptionBudget(pdb *policy.PodDisruptionBudget, events *api.EventList) (string, error) {
return tabbedString(func(out io.Writer) error {
w := NewPrefixWriter(out)
w.Write(LEVEL_0, "Name:\t%s\n", pdb.Name)
Expand All @@ -2732,15 +2727,10 @@ func (p *PodDisruptionBudgetDescriber) Describe(namespace, name string, describe
w.Write(LEVEL_2, "Current:\t%d\n", pdb.Status.CurrentHealthy)
w.Write(LEVEL_2, "Desired:\t%d\n", pdb.Status.DesiredHealthy)
w.Write(LEVEL_2, "Total:\t%d\n", pdb.Status.ExpectedPods)
if describerSettings.ShowEvents {
events, err := p.Core().Events(namespace).Search(api.Scheme, pdb)
if err != nil {
return err
}
if events != nil {
DescribeEvents(events, w)
}
if events != nil {
DescribeEvents(events, w)
}

return nil
})
}
Expand Down Expand Up @@ -2886,19 +2876,13 @@ func (fn typeFunc) Describe(exact interface{}, extra ...interface{}) (string, er
return s, err
}

// printLabelsMultilineWithFilter prints filtered multiple labels with a proper alignment.
func printLabelsMultilineWithFilter(w PrefixWriter, title string, labels map[string]string, skip sets.String) {
printLabelsMultilineWithIndent(w, "", title, "\t", labels, skip)
}

// printLabelsMultiline prints multiple labels with a proper alignment.
func printLabelsMultiline(w PrefixWriter, title string, labels map[string]string) {
printLabelsMultilineWithIndent(w, "", title, "\t", labels, sets.NewString())
}

// printLabelsMultiline prints multiple labels with a user-defined alignment.
func printLabelsMultilineWithIndent(w PrefixWriter, initialIndent, title, innerIndent string, labels map[string]string, skip sets.String) {

w.Write(LEVEL_0, "%s%s:%s", initialIndent, title, innerIndent)

if labels == nil || len(labels) == 0 {
Expand Down Expand Up @@ -3077,16 +3061,6 @@ func (list SortableVolumeMounts) Less(i, j int) bool {
return list[i].MountPath < list[j].MountPath
}

// SortedQoSResourceNames returns the sorted resource names of a QoS list.
func SortedQoSResourceNames(list qos.QOSList) []api.ResourceName {
resources := make([]api.ResourceName, 0, len(list))
for res := range list {
resources = append(resources, api.ResourceName(res))
}
sort.Sort(SortableResourceNames(resources))
return resources
}

func versionedClientsetForDeployment(internalClient clientset.Interface) versionedclientset.Interface {
if internalClient == nil {
return &versionedclientset.Clientset{}
Expand Down