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

kubectl describe: show annotations #35094

Merged
merged 1 commit into from
Feb 28, 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
76 changes: 71 additions & 5 deletions pkg/printers/internalversion/describe.go
Expand Up @@ -243,6 +243,7 @@ func describeNamespace(namespace *api.Namespace, resourceQuotaList *api.Resource
w := &PrefixWriter{out}
w.Write(LEVEL_0, "Name:\t%s\n", namespace.Name)
printLabelsMultiline(w, "Labels", namespace.Labels)
printAnnotationsMultiline(w, "Annotations", namespace.Annotations)
w.Write(LEVEL_0, "Status:\t%s\n", string(namespace.Status.Phase))
if resourceQuotaList != nil {
w.Write(LEVEL_0, "\n")
Expand Down Expand Up @@ -522,6 +523,7 @@ func describePod(pod *api.Pod, events *api.EventList) (string, error) {
w.Write(LEVEL_0, "Start Time:\t%s\n", pod.Status.StartTime.Time.Format(time.RFC1123Z))
}
printLabelsMultiline(w, "Labels", pod.Labels)
printAnnotationsMultiline(w, "Annotations", pod.Annotations)
if pod.DeletionTimestamp != nil {
w.Write(LEVEL_0, "Status:\tTerminating (expires %s)\n", pod.DeletionTimestamp.Time.Format(time.RFC1123Z))
w.Write(LEVEL_0, "Termination Grace Period:\t%ds\n", *pod.DeletionGracePeriodSeconds)
Expand Down Expand Up @@ -800,6 +802,7 @@ func (d *PersistentVolumeDescriber) Describe(namespace, name string, describerSe
w := &PrefixWriter{out}
w.Write(LEVEL_0, "Name:\t%s\n", pv.Name)
printLabelsMultiline(w, "Labels", pv.Labels)
printAnnotationsMultiline(w, "Annotations", pv.Annotations)
w.Write(LEVEL_0, "StorageClass:\t%s\n", storageutil.GetStorageClassAnnotation(pv.ObjectMeta))
w.Write(LEVEL_0, "Status:\t%s\n", pv.Status.Phase)
if pv.Spec.ClaimRef != nil {
Expand Down Expand Up @@ -879,6 +882,7 @@ func (d *PersistentVolumeClaimDescriber) Describe(namespace, name string, descri
w.Write(LEVEL_0, "Status:\t%v\n", pvc.Status.Phase)
w.Write(LEVEL_0, "Volume:\t%s\n", pvc.Spec.VolumeName)
printLabelsMultiline(w, "Labels", pvc.Labels)
printAnnotationsMultiline(w, "Annotations", pvc.Annotations)
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 @@ -1219,6 +1223,7 @@ func describeReplicationController(controller *api.ReplicationController, events
}
w.Write(LEVEL_0, "Selector:\t%s\n", labels.FormatLabels(controller.Spec.Selector))
printLabelsMultiline(w, "Labels", controller.Labels)
printAnnotationsMultiline(w, "Annotations", controller.Annotations)
w.Write(LEVEL_0, "Replicas:\t%d current / %d desired\n", controller.Status.Replicas, controller.Spec.Replicas)
w.Write(LEVEL_0, "Pods Status:\t%d Running / %d Waiting / %d Succeeded / %d Failed\n", running, waiting, succeeded, failed)

Expand All @@ -1240,7 +1245,7 @@ func DescribePodTemplate(template *api.PodTemplateSpec, out io.Writer) {
}
printLabelsMultiline(w, " Labels", template.Labels)
if len(template.Annotations) > 0 {
printLabelsMultiline(w, " Annotations", template.Annotations)
printAnnotationsMultiline(w, " Annotations", template.Annotations)
}
if len(template.Spec.ServiceAccountName) > 0 {
w.Write(LEVEL_1, "Service Account:\t%s\n", template.Spec.ServiceAccountName)
Expand Down Expand Up @@ -1289,6 +1294,7 @@ func describeReplicaSet(rs *extensions.ReplicaSet, events *api.EventList, runnin
w.Write(LEVEL_0, "Image(s):\t%s\n", makeImageList(&rs.Spec.Template.Spec))
w.Write(LEVEL_0, "Selector:\t%s\n", metav1.FormatLabelSelector(rs.Spec.Selector))
printLabelsMultiline(w, "Labels", rs.Labels)
printAnnotationsMultiline(w, "Annotations", rs.Annotations)
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 {
Expand Down Expand Up @@ -1344,6 +1350,7 @@ func describeJob(job *batch.Job, events *api.EventList) (string, error) {
w.Write(LEVEL_0, "Active Deadline Seconds:\t%ds\n", *job.Spec.ActiveDeadlineSeconds)
}
printLabelsMultiline(w, "Labels", job.Labels)
printAnnotationsMultiline(w, "Annotations", job.Annotations)
w.Write(LEVEL_0, "Pods Statuses:\t%d Running / %d Succeeded / %d Failed\n", job.Status.Active, job.Status.Succeeded, job.Status.Failed)
describeVolumes(job.Spec.Template.Spec.Volumes, w, "")
if events != nil {
Expand Down Expand Up @@ -1387,6 +1394,7 @@ func describeCronJob(scheduledJob *batch.CronJob, events *api.EventList) (string
}
describeJobTemplate(scheduledJob.Spec.JobTemplate, w)
printLabelsMultiline(w, "Labels", scheduledJob.Labels)
printAnnotationsMultiline(w, "Annotations", scheduledJob.Annotations)
if scheduledJob.Status.LastScheduleTime != nil {
w.Write(LEVEL_0, "Last Schedule Time:\t%s\n", scheduledJob.Status.LastScheduleTime.Time.Format(time.RFC1123Z))
} else {
Expand Down Expand Up @@ -1484,6 +1492,7 @@ func describeDaemonSet(daemon *extensions.DaemonSet, events *api.EventList, runn
w.Write(LEVEL_0, "Selector:\t%s\n", selector)
w.Write(LEVEL_0, "Node-Selector:\t%s\n", labels.FormatLabels(daemon.Spec.Template.Spec.NodeSelector))
printLabelsMultiline(w, "Labels", daemon.Labels)
printAnnotationsMultiline(w, "Annotations", daemon.Annotations)
w.Write(LEVEL_0, "Desired Number of Nodes Scheduled: %d\n", daemon.Status.DesiredNumberScheduled)
w.Write(LEVEL_0, "Current Number of Nodes Scheduled: %d\n", daemon.Status.CurrentNumberScheduled)
w.Write(LEVEL_0, "Number of Nodes Misscheduled: %d\n", daemon.Status.NumberMisscheduled)
Expand Down Expand Up @@ -1518,7 +1527,7 @@ func describeSecret(secret *api.Secret) (string, error) {
w.Write(LEVEL_0, "Namespace:\t%s\n", secret.Namespace)
printLabelsMultiline(w, "Labels", secret.Labels)
skipAnnotations := sets.NewString(annotations.LastAppliedConfigAnnotation)
printLabelsMultilineWithFilter(w, "Annotations", secret.Annotations, skipAnnotations)
printAnnotationsMultilineWithFilter(w, "Annotations", secret.Annotations, skipAnnotations)

w.Write(LEVEL_0, "\nType:\t%s\n", secret.Type)

Expand Down Expand Up @@ -1694,6 +1703,7 @@ func describeService(service *api.Service, endpoints *api.Endpoints, events *api
w.Write(LEVEL_0, "Name:\t%s\n", service.Name)
w.Write(LEVEL_0, "Namespace:\t%s\n", service.Namespace)
printLabelsMultiline(w, "Labels", service.Labels)
printAnnotationsMultiline(w, "Annotations", service.Annotations)
w.Write(LEVEL_0, "Selector:\t%s\n", labels.FormatLabels(service.Spec.Selector))
w.Write(LEVEL_0, "Type:\t%s\n", service.Spec.Type)
w.Write(LEVEL_0, "IP:\t%s\n", service.Spec.ClusterIP)
Expand Down Expand Up @@ -1755,6 +1765,7 @@ func describeEndpoints(ep *api.Endpoints, events *api.EventList) (string, error)
w.Write(LEVEL_0, "Name:\t%s\n", ep.Name)
w.Write(LEVEL_0, "Namespace:\t%s\n", ep.Namespace)
printLabelsMultiline(w, "Labels", ep.Labels)
printAnnotationsMultiline(w, "Annotations", ep.Annotations)

w.Write(LEVEL_0, "Subsets:\n")
for i := range ep.Subsets {
Expand Down Expand Up @@ -1861,6 +1872,7 @@ func describeServiceAccount(serviceAccount *api.ServiceAccount, tokens []api.Sec
w.Write(LEVEL_0, "Name:\t%s\n", serviceAccount.Name)
w.Write(LEVEL_0, "Namespace:\t%s\n", serviceAccount.Namespace)
printLabelsMultiline(w, "Labels", serviceAccount.Labels)
printAnnotationsMultiline(w, "Annotations", serviceAccount.Annotations)
w.WriteLine()

var (
Expand Down Expand Up @@ -1957,6 +1969,7 @@ func describeNode(node *api.Node, nodeNonTerminatedPodsList *api.PodList, events
w.Write(LEVEL_0, "Name:\t%s\n", node.Name)
w.Write(LEVEL_0, "Role:\t%s\n", findNodeRole(node))
printLabelsMultiline(w, "Labels", node.Labels)
printAnnotationsMultiline(w, "Annotations", node.Annotations)
printNodeTaintsMultiline(w, "Taints", node.Spec.Taints)
w.Write(LEVEL_0, "CreationTimestamp:\t%s\n", node.CreationTimestamp.Time.Format(time.RFC1123Z))
w.Write(LEVEL_0, "Phase:\t%v\n", node.Status.Phase)
Expand Down Expand Up @@ -2159,7 +2172,7 @@ func (d *HorizontalPodAutoscalerDescriber) Describe(namespace, name string, desc
w.Write(LEVEL_0, "Name:\t%s\n", hpa.Name)
w.Write(LEVEL_0, "Namespace:\t%s\n", hpa.Namespace)
printLabelsMultiline(w, "Labels", hpa.Labels)
printLabelsMultiline(w, "Annotations", hpa.Annotations)
printAnnotationsMultiline(w, "Annotations", hpa.Annotations)
w.Write(LEVEL_0, "CreationTimestamp:\t%s\n", hpa.CreationTimestamp.Time.Format(time.RFC1123Z))
w.Write(LEVEL_0, "Reference:\t%s/%s\n",
hpa.Spec.ScaleTargetRef.Kind,
Expand Down Expand Up @@ -2355,6 +2368,7 @@ func (dd *DeploymentDescriber) Describe(namespace, name string, describerSetting
w.Write(LEVEL_0, "Namespace:\t%s\n", d.ObjectMeta.Namespace)
w.Write(LEVEL_0, "CreationTimestamp:\t%s\n", d.CreationTimestamp.Time.Format(time.RFC1123Z))
printLabelsMultiline(w, "Labels", d.Labels)
printAnnotationsMultiline(w, "Annotations", d.Annotations)
w.Write(LEVEL_0, "Selector:\t%s\n", selector)
w.Write(LEVEL_0, "Replicas:\t%d desired | %d updated | %d total | %d available | %d unavailable\n", *(d.Spec.Replicas), d.Status.UpdatedReplicas, d.Status.Replicas, d.Status.AvailableReplicas, d.Status.UnavailableReplicas)
w.Write(LEVEL_0, "StrategyType:\t%s\n", d.Spec.Strategy.Type)
Expand Down Expand Up @@ -2492,7 +2506,7 @@ func describeConfigMap(configMap *api.ConfigMap) (string, error) {
w.Write(LEVEL_0, "Name:\t%s\n", configMap.Name)
w.Write(LEVEL_0, "Namespace:\t%s\n", configMap.Namespace)
printLabelsMultiline(w, "Labels", configMap.Labels)
printLabelsMultiline(w, "Annotations", configMap.Annotations)
printAnnotationsMultiline(w, "Annotations", configMap.Annotations)

w.Write(LEVEL_0, "\nData\n====\n")
for k, v := range configMap.Data {
Expand Down Expand Up @@ -2567,7 +2581,7 @@ func describeNetworkPolicy(networkPolicy *extensions.NetworkPolicy) (string, err
w.Write(LEVEL_0, "Name:\t%s\n", networkPolicy.Name)
w.Write(LEVEL_0, "Namespace:\t%s\n", networkPolicy.Namespace)
printLabelsMultiline(w, "Labels", networkPolicy.Labels)
printLabelsMultiline(w, "Annotations", networkPolicy.Annotations)
printAnnotationsMultiline(w, "Annotations", networkPolicy.Annotations)

return nil
})
Expand Down Expand Up @@ -2998,3 +3012,55 @@ func versionedClientsetForDeployment(internalClient clientset.Interface) version
ExtensionsV1beta1Client: extensionsclientset.New(internalClient.Extensions().RESTClient()),
}
}

var maxAnnotationLen = 200

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

// printAnnotationsMultiline prints multiple annotations with a proper alignment.
func printAnnotationsMultiline(w *PrefixWriter, title string, annotations map[string]string) {
printAnnotationsMultilineWithIndent(w, "", title, "\t", annotations, sets.NewString())
}

// printAnnotationsMultilineWithIndent prints multiple annotations with a user-defined alignment.
// If annotation string is too long, we omit chars more than 200 length.
func printAnnotationsMultilineWithIndent(w *PrefixWriter, initialIndent, title, innerIndent string, annotations map[string]string, skip sets.String) {

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

if len(annotations) == 0 {
w.WriteLine("<none>")
return
}

// to print labels in the sorted order
keys := make([]string, 0, len(annotations))
for key := range annotations {
if skip.Has(key) {
continue
}
keys = append(keys, key)
}
if len(annotations) == 0 {
w.WriteLine("<none>")
return
}
sort.Strings(keys)

for i, key := range keys {
if i != 0 {
w.Write(LEVEL_0, initialIndent)
w.Write(LEVEL_0, innerIndent)
}
line := fmt.Sprintf("%s=%s", key, annotations[key])
if len(line) > maxAnnotationLen {
w.Write(LEVEL_0, "%s...\n", line[:maxAnnotationLen])
} else {
w.Write(LEVEL_0, "%s\n", line)
}
i++
}
}
34 changes: 34 additions & 0 deletions pkg/printers/internalversion/describe_test.go
Expand Up @@ -1265,3 +1265,37 @@ func TestDescribeEvents(t *testing.T) {
}
}
}

func TestPrintLabelsMultiline(t *testing.T) {
var maxLenAnnotationStr string = "MaxLenAnnotation=Multicast addressing can be used in the link layer (Layer 2 in the OSI model), such as Ethernet multicast, and at the internet layer (Layer 3 for OSI) for Internet Protocol Version 4 "
testCases := []struct {
annotations map[string]string
expectPrint string
}{
{
annotations: map[string]string{"col1": "asd", "COL2": "zxc"},
expectPrint: "Annotations:\tCOL2=zxc\n\tcol1=asd\n",
},
{
annotations: map[string]string{"MaxLenAnnotation": maxLenAnnotationStr[17:]},
expectPrint: "Annotations:\t" + maxLenAnnotationStr + "\n",
},
{
annotations: map[string]string{"MaxLenAnnotation": maxLenAnnotationStr[17:] + "1"},
expectPrint: "Annotations:\t" + maxLenAnnotationStr + "...\n",
},
{
annotations: map[string]string{},
expectPrint: "Annotations:\t<none>\n",
},
}
for i, testCase := range testCases {
out := new(bytes.Buffer)
writer := &PrefixWriter{out}
printAnnotationsMultiline(writer, "Annotations", testCase.annotations)
output := out.String()
if output != testCase.expectPrint {
t.Errorf("Test case %d: expected to find %q in output: %q", i, testCase.expectPrint, output)
}
}
}
5 changes: 5 additions & 0 deletions test/e2e/kubectl.go
Expand Up @@ -718,6 +718,7 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
{"Node:"},
{"Labels:", "app=redis"},
{"role=master"},
{"Annotations:"},
{"Status:", "Running"},
{"IP:"},
{"Controllers:", "ReplicationController/redis-master"},
Expand All @@ -737,6 +738,7 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
{"Selector:", "app=redis,role=master"},
{"Labels:", "app=redis"},
{"role=master"},
{"Annotations:"},
{"Replicas:", "1 current", "1 desired"},
{"Pods Status:", "1 Running", "0 Waiting", "0 Succeeded", "0 Failed"},
// {"Events:"} would ordinarily go in the list
Expand All @@ -754,6 +756,7 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
{"Namespace:", ns},
{"Labels:", "app=redis"},
{"role=master"},
{"Annotations:"},
{"Selector:", "app=redis", "role=master"},
{"Type:", "ClusterIP"},
{"IP:"},
Expand All @@ -771,6 +774,7 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
requiredStrings = [][]string{
{"Name:", node.Name},
{"Labels:"},
{"Annotations:"},
{"CreationTimestamp:"},
{"Conditions:"},
{"Type", "Status", "LastHeartbeatTime", "LastTransitionTime", "Reason", "Message"},
Expand All @@ -790,6 +794,7 @@ var _ = framework.KubeDescribe("Kubectl client", func() {
requiredStrings = [][]string{
{"Name:", ns},
{"Labels:"},
{"Annotations:"},
{"Status:", "Active"}}
checkOutput(output, requiredStrings)

Expand Down