diff --git a/pkg/printers/internalversion/describe.go b/pkg/printers/internalversion/describe.go index e3491634c3c..1fe2b0ffd1a 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 8bdfd943195..a1840c28c32 100644 --- a/pkg/printers/internalversion/describe_test.go +++ b/pkg/printers/internalversion/describe_test.go @@ -1163,6 +1163,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 {