Access a property in the body of a kubernetes resource using a field path

2/27/2022

I want to get the values of the fields declared in the downwardAPI section of a Pod.

apiVersion: v1
kind: Pod
metadata:
  name: sample
  namespace: default
spec:
  containers:
  - image: rpa
    imagePullPolicy: Always
    name: testbot
    volumeMounts:
    - mountPath: /etc/pod-info
      name: pod-info
  volumes:
  - downwardAPI:
      items:
      - fieldRef:
          apiVersion: v1
          fieldPath: metadata.labels
        path: labels
      - fieldRef:
          apiVersion: v1
          fieldPath: metadata.name
        path: pod-name
      - fieldRef:
          apiVersion: v1
          fieldPath: metadata.namespace
        path: pod-namespace
    name: pod-info

Using client-go, I can use pod.Spec.Volumes[0].DownwardAPI.Items to get the item slice including the fieldPath. But I would now need to dynamically able to fetch whatever values has been declared in the fieldPath. So, from the first item, I would like to access the value of metadata.labels. I could do pod.ObjectMeta.Labels but I would like to access the field dynamically. In terms of Javascript it would have been something like

var foo="metadata.labels"
var fooarr = foo.split(".")
var bar={
  metadata:{
    labels: "foobar"
  }
}
var temp = oof
for(lm of lmaoarr){
  temp = temp[lm]
}
console.log(temp)

How do I do something similar using client-go?

-- Sayak Mukhopadhyay
client-go
go
kubernetes

1 Answer

2/28/2022

The standard kubelet code has logic to translate the downward API fields into environment variables. It is neither simple nor generic, though: at the bottom of the stack, only the specific fields listed in the Kubernetes documentation are supported. It would be incomplete, but not wrong or inconsistent with standard Kubernetes, to just match on these specific fields:

for _, item := range downwardApiObject.Items {
        switch item.FieldPath.FieldRef {
        case "metadata.name":
                return pod.ObjectMeta.Name
        }
}

The actual code:

  1. Calls pods.ConvertDownwardAPIFieldLabel which does some very lightweight normalization and validation: subscripts are only allowed on metadata.annotations and metadata.labels, only the dozen or so specific field names are allowed, and spec.host is rewritten to spec.nodeName.
  2. Handles the spec.* and status.* variables that depend on non-metadata fields in the pod spec or runtime data.
  3. Delegates to fieldpath.ExtractFieldPathAsString which knows how to handle the metadata.* variables.

The k8s.io/kubernetes/pkg/fieldpath package contains a couple of helpers that are used in processing the downward API, and a really short answer to your specific question could be just to call fieldpath.ExtractFieldPathAsString passing it the Pod object, which will handle the metadata fields but nothing else.

-- David Maze
Source: StackOverflow