1
16
17 package fieldpath
18
19 import (
20 "fmt"
21 "sort"
22 "strconv"
23 "strings"
24
25 "k8s.io/apimachinery/pkg/api/meta"
26 "k8s.io/apimachinery/pkg/util/validation"
27 )
28
29
30 func FormatMap(m map[string]string) (fmtStr string) {
31
32 keys := make([]string, 0, len(m))
33 var grow int
34 for k, v := range m {
35 keys = append(keys, k)
36
37 grow += len(k) + len(v) + 4
38 }
39 sort.Strings(keys)
40
41 dst := make([]byte, 0, grow)
42 for _, key := range keys {
43 if len(dst) > 0 {
44 dst = append(dst, '\n')
45 }
46 dst = append(dst, key...)
47 dst = append(dst, '=')
48 dst = strconv.AppendQuote(dst, m[key])
49 }
50 return string(dst)
51 }
52
53
54
55
56 func ExtractFieldPathAsString(obj interface{}, fieldPath string) (string, error) {
57 accessor, err := meta.Accessor(obj)
58 if err != nil {
59 return "", err
60 }
61
62 if path, subscript, ok := SplitMaybeSubscriptedPath(fieldPath); ok {
63 switch path {
64 case "metadata.annotations":
65 if errs := validation.IsQualifiedName(strings.ToLower(subscript)); len(errs) != 0 {
66 return "", fmt.Errorf("invalid key subscript in %s: %s", fieldPath, strings.Join(errs, ";"))
67 }
68 return accessor.GetAnnotations()[subscript], nil
69 case "metadata.labels":
70 if errs := validation.IsQualifiedName(subscript); len(errs) != 0 {
71 return "", fmt.Errorf("invalid key subscript in %s: %s", fieldPath, strings.Join(errs, ";"))
72 }
73 return accessor.GetLabels()[subscript], nil
74 default:
75 return "", fmt.Errorf("fieldPath %q does not support subscript", fieldPath)
76 }
77 }
78
79 switch fieldPath {
80 case "metadata.annotations":
81 return FormatMap(accessor.GetAnnotations()), nil
82 case "metadata.labels":
83 return FormatMap(accessor.GetLabels()), nil
84 case "metadata.name":
85 return accessor.GetName(), nil
86 case "metadata.namespace":
87 return accessor.GetNamespace(), nil
88 case "metadata.uid":
89 return string(accessor.GetUID()), nil
90 }
91
92 return "", fmt.Errorf("unsupported fieldPath: %v", fieldPath)
93 }
94
95
96
97
98
99
100
101
102
103
104
105
106
107 func SplitMaybeSubscriptedPath(fieldPath string) (string, string, bool) {
108 if !strings.HasSuffix(fieldPath, "']") {
109 return fieldPath, "", false
110 }
111 s := strings.TrimSuffix(fieldPath, "']")
112 parts := strings.SplitN(s, "['", 2)
113 if len(parts) < 2 {
114 return fieldPath, "", false
115 }
116 if len(parts[0]) == 0 {
117 return fieldPath, "", false
118 }
119 return parts[0], parts[1], true
120 }
121
View as plain text