From 70b3c20042fe7e49f83a718ab7268e4478e3f16d Mon Sep 17 00:00:00 2001 From: Guoliang Wang Date: Wed, 13 Jun 2018 22:58:42 +0800 Subject: [PATCH] Add CSI volume attributes for kubectl describe pv --- pkg/printers/internalversion/describe.go | 46 +++++++++++- pkg/printers/internalversion/describe_test.go | 74 +++++++++++++++++++ 2 files changed, 118 insertions(+), 2 deletions(-) diff --git a/pkg/printers/internalversion/describe.go b/pkg/printers/internalversion/describe.go index 1e27451bea0..ad2a39f5ed8 100644 --- a/pkg/printers/internalversion/describe.go +++ b/pkg/printers/internalversion/describe.go @@ -1129,6 +1129,48 @@ func printCSIPersistentVolumeSource(csi *api.CSIPersistentVolumeSource, w Prefix " VolumeHandle:\t%v\n"+ " ReadOnly:\t%v\n", csi.Driver, csi.VolumeHandle, csi.ReadOnly) + printCSIPersistentVolumeAttributesMultiline(w, "VolumeAttributes", csi.VolumeAttributes) +} + +func printCSIPersistentVolumeAttributesMultiline(w PrefixWriter, title string, annotations map[string]string) { + printCSIPersistentVolumeAttributesMultilineIndent(w, "", title, "\t", annotations, sets.NewString()) +} + +func printCSIPersistentVolumeAttributesMultilineIndent(w PrefixWriter, initialIndent, title, innerIndent string, attributes map[string]string, skip sets.String) { + w.Write(LEVEL_2, "%s%s:%s", initialIndent, title, innerIndent) + + if len(attributes) == 0 { + w.WriteLine("") + return + } + + // to print labels in the sorted order + keys := make([]string, 0, len(attributes)) + for key := range attributes { + if skip.Has(key) { + continue + } + keys = append(keys, key) + } + if len(attributes) == 0 { + w.WriteLine("") + return + } + sort.Strings(keys) + + for i, key := range keys { + if i != 0 { + w.Write(LEVEL_2, initialIndent) + w.Write(LEVEL_2, innerIndent) + } + line := fmt.Sprintf("%s=%s", key, attributes[key]) + if len(line) > maxAnnotationLen { + w.Write(LEVEL_2, "%s...\n", line[:maxAnnotationLen]) + } else { + w.Write(LEVEL_2, "%s\n", line) + } + i++ + } } type PersistentVolumeDescriber struct { @@ -1197,8 +1239,8 @@ func describePersistentVolume(pv *api.PersistentVolume, events *api.EventList) ( return tabbedString(func(out io.Writer) error { w := NewPrefixWriter(out) w.Write(LEVEL_0, "Name:\t%s\n", pv.Name) - printLabelsMultiline(w, "Labels", pv.Labels) - printAnnotationsMultiline(w, "Annotations", pv.Annotations) + printLabelsMultiline(w, "Labels", pv.ObjectMeta.Labels) + printAnnotationsMultiline(w, "Annotations", pv.ObjectMeta.Annotations) w.Write(LEVEL_0, "Finalizers:\t%v\n", pv.ObjectMeta.Finalizers) w.Write(LEVEL_0, "StorageClass:\t%s\n", helper.GetPersistentVolumeClass(pv)) if pv.ObjectMeta.DeletionTimestamp != nil { diff --git a/pkg/printers/internalversion/describe_test.go b/pkg/printers/internalversion/describe_test.go index bafea3a899d..89d84a82918 100644 --- a/pkg/printers/internalversion/describe_test.go +++ b/pkg/printers/internalversion/describe_test.go @@ -1161,6 +1161,80 @@ func TestPersistentVolumeDescriber(t *testing.T) { }, expectedElements: []string{"Terminating (lasts 10y)"}, }, + { + name: "test16", + plugin: "local", + pv: &api.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar", + GenerateName: "test-GenerateName", + UID: "test-UID", + CreationTimestamp: metav1.Time{Time: time.Now()}, + DeletionTimestamp: &metav1.Time{Time: time.Now()}, + DeletionGracePeriodSeconds: new(int64), + Labels: map[string]string{"label1": "label1", "label2": "label2", "label3": "label3"}, + Annotations: map[string]string{"annotation1": "annotation1", "annotation2": "annotation2", "annotation3": "annotation3"}, + }, + Spec: api.PersistentVolumeSpec{ + PersistentVolumeSource: api.PersistentVolumeSource{ + Local: &api.LocalVolumeSource{}, + }, + NodeAffinity: &api.VolumeNodeAffinity{ + Required: &api.NodeSelector{ + NodeSelectorTerms: []api.NodeSelectorTerm{ + { + MatchExpressions: []api.NodeSelectorRequirement{ + { + Key: "foo", + Operator: "In", + Values: []string{"val1", "val2"}, + }, + { + Key: "foo", + Operator: "Exists", + }, + }, + }, + }, + }, + }, + }, + }, + expectedElements: []string{"Node Affinity", "Required Terms", "Term 0", + "foo in [val1, val2]", + "foo exists"}, + }, + { + name: "test17", + plugin: "local", + pv: &api.PersistentVolume{ + ObjectMeta: metav1.ObjectMeta{ + Name: "bar", + GenerateName: "test-GenerateName", + UID: "test-UID", + CreationTimestamp: metav1.Time{Time: time.Now()}, + DeletionTimestamp: &metav1.Time{Time: time.Now()}, + DeletionGracePeriodSeconds: new(int64), + Labels: map[string]string{"label1": "label1", "label2": "label2", "label3": "label3"}, + Annotations: map[string]string{"annotation1": "annotation1", "annotation2": "annotation2", "annotation3": "annotation3"}, + }, + Spec: api.PersistentVolumeSpec{ + PersistentVolumeSource: api.PersistentVolumeSource{ + CSI: &api.CSIPersistentVolumeSource{ + Driver: "drive", + VolumeHandle: "handler", + ReadOnly: true, + VolumeAttributes: map[string]string{ + "Attribute1": "Value1", + "Attribute2": "Value2", + "Attribute3": "Value3", + }, + }, + }, + }, + }, + expectedElements: []string{"Driver", "VolumeHandle", "ReadOnly", "VolumeAttributes"}, + }, } for _, test := range testCases {