mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-19 17:16:12 +00:00
Expose single annotation/label via downward API
This commit is contained in:
@@ -42,7 +42,20 @@ func ExtractFieldPathAsString(obj interface{}, fieldPath string) (string, error)
|
||||
return "", nil
|
||||
}
|
||||
|
||||
switch fieldPath {
|
||||
path, subscript := SplitMaybeSubscriptedPath(fieldPath)
|
||||
|
||||
if len(subscript) > 0 {
|
||||
switch path {
|
||||
case "metadata.annotations":
|
||||
return accessor.GetAnnotations()[subscript], nil
|
||||
case "metadata.labels":
|
||||
return accessor.GetLabels()[subscript], nil
|
||||
default:
|
||||
return "", fmt.Errorf("fieldPath %q does not support subscript", fieldPath)
|
||||
}
|
||||
}
|
||||
|
||||
switch path {
|
||||
case "metadata.annotations":
|
||||
return FormatMap(accessor.GetAnnotations()), nil
|
||||
case "metadata.labels":
|
||||
@@ -57,3 +70,29 @@ func ExtractFieldPathAsString(obj interface{}, fieldPath string) (string, error)
|
||||
|
||||
return "", fmt.Errorf("unsupported fieldPath: %v", fieldPath)
|
||||
}
|
||||
|
||||
// SplitMaybeSubscriptedPath checks whether the specified fieldPath is
|
||||
// subscripted, and
|
||||
// - if yes, this function splits the fieldPath into path and subscript, and
|
||||
// returns (path, subscript).
|
||||
// - if no, this function returns (fieldPath, "").
|
||||
//
|
||||
// Example inputs and outputs:
|
||||
// - "metadata.annotations['myKey']" --> ("metadata.annotations", "myKey")
|
||||
// - "metadata.annotations['a[b]c']" --> ("metadata.annotations", "a[b]c")
|
||||
// - "metadata.labels" --> ("metadata.labels", "")
|
||||
// - "metadata.labels['']" --> ("metadata.labels", "")
|
||||
func SplitMaybeSubscriptedPath(fieldPath string) (string, string) {
|
||||
if !strings.HasSuffix(fieldPath, "']") {
|
||||
return fieldPath, ""
|
||||
}
|
||||
s := strings.TrimSuffix(fieldPath, "']")
|
||||
parts := strings.SplitN(s, "['", 2)
|
||||
if len(parts) < 2 {
|
||||
return fieldPath, ""
|
||||
}
|
||||
if len(parts[0]) == 0 || len(parts[1]) == 0 {
|
||||
return fieldPath, ""
|
||||
}
|
||||
return parts[0], parts[1]
|
||||
}
|
||||
|
@@ -88,6 +88,16 @@ func TestExtractFieldPathAsString(t *testing.T) {
|
||||
},
|
||||
expectedValue: "builder=\"john-doe\"",
|
||||
},
|
||||
{
|
||||
name: "ok - annotation",
|
||||
fieldPath: "metadata.annotations['spec.pod.beta.kubernetes.io/statefulset-index']",
|
||||
obj: &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Annotations: map[string]string{"spec.pod.beta.kubernetes.io/statefulset-index": "1"},
|
||||
},
|
||||
},
|
||||
expectedValue: "1",
|
||||
},
|
||||
|
||||
{
|
||||
name: "invalid expression",
|
||||
@@ -99,6 +109,16 @@ func TestExtractFieldPathAsString(t *testing.T) {
|
||||
},
|
||||
expectedMessageFragment: "unsupported fieldPath",
|
||||
},
|
||||
{
|
||||
name: "invalid annotation",
|
||||
fieldPath: "metadata.annotations['unknown.key']",
|
||||
obj: &v1.Pod{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Annotations: map[string]string{"foo": "bar"},
|
||||
},
|
||||
},
|
||||
expectedMessageFragment: "unsupported fieldPath",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
@@ -116,3 +136,79 @@ func TestExtractFieldPathAsString(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSplitMaybeSubscriptedPath(t *testing.T) {
|
||||
cases := []struct {
|
||||
fieldPath string
|
||||
expectedPath string
|
||||
expectedSubscript string
|
||||
}{
|
||||
{
|
||||
fieldPath: "metadata.annotations['key']",
|
||||
expectedPath: "metadata.annotations",
|
||||
expectedSubscript: "key",
|
||||
},
|
||||
{
|
||||
fieldPath: "metadata.annotations['a[b']c']",
|
||||
expectedPath: "metadata.annotations",
|
||||
expectedSubscript: "a[b']c",
|
||||
},
|
||||
{
|
||||
fieldPath: "metadata.labels['['key']",
|
||||
expectedPath: "metadata.labels",
|
||||
expectedSubscript: "['key",
|
||||
},
|
||||
{
|
||||
fieldPath: "metadata.labels['key']']",
|
||||
expectedPath: "metadata.labels",
|
||||
expectedSubscript: "key']",
|
||||
},
|
||||
{
|
||||
fieldPath: "metadata.labels[ 'key' ]",
|
||||
expectedPath: "metadata.labels[ 'key' ]",
|
||||
expectedSubscript: "",
|
||||
},
|
||||
{
|
||||
fieldPath: "metadata.labels['']",
|
||||
expectedPath: "metadata.labels['']",
|
||||
expectedSubscript: "",
|
||||
},
|
||||
{
|
||||
fieldPath: "metadata.labels[' ']",
|
||||
expectedPath: "metadata.labels",
|
||||
expectedSubscript: " ",
|
||||
},
|
||||
{
|
||||
fieldPath: "metadata.labels[]",
|
||||
expectedPath: "metadata.labels[]",
|
||||
expectedSubscript: "",
|
||||
},
|
||||
{
|
||||
fieldPath: "metadata.labels[']",
|
||||
expectedPath: "metadata.labels[']",
|
||||
expectedSubscript: "",
|
||||
},
|
||||
{
|
||||
fieldPath: "metadata.labels['key']foo",
|
||||
expectedPath: "metadata.labels['key']foo",
|
||||
expectedSubscript: "",
|
||||
},
|
||||
{
|
||||
fieldPath: "['key']",
|
||||
expectedPath: "['key']",
|
||||
expectedSubscript: "",
|
||||
},
|
||||
{
|
||||
fieldPath: "metadata.labels",
|
||||
expectedPath: "metadata.labels",
|
||||
expectedSubscript: "",
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
path, subscript := SplitMaybeSubscriptedPath(tc.fieldPath)
|
||||
if path != tc.expectedPath || subscript != tc.expectedSubscript {
|
||||
t.Errorf("SplitMaybeSubscriptedPath(%q) = (%q, %q), expect (%q, %q)",
|
||||
tc.fieldPath, path, subscript, tc.expectedPath, tc.expectedSubscript)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user