I write a lot of operations and integrations with Kubernetes those days. You can follow my journey in its dedicated section on this blog “Building Kubernetes”.

I had to write a function recently capable of filtering pods based on assigned annotations.

const ( ProfefeEnabledAnnotation = "profefe.com/enable" ) // GetSelectedPods returns all the pods with the profefe annotation enabled // filtered by the selected labels func GetSelectedPods ( clientset kubernetes . Interface , namespace string , listOpt metav1 . ListOptions ) ([] v1 . Pod , error ) { target := [] v1 . Pod {} pods , err := clientset . CoreV1 () . Pods ( namespace ) . List ( listOpt ) if err != nil { return target , err } for _ , pod := range pods . Items { enabled , ok := pod . Annotations [ ProfefeEnabledAnnotation ] if ok && enabled == "true" && pod . Status . Phase == v1 . PodRunning { target = append ( target , pod ) } } return target , nil }

This function is pretty easy, but it has a good amount of assertions that we can check. Even more when we have a so well scoped functions writing tests should be almost mandatory.

The returned list of pods should only contains pods with the ProfefeEnabledAnnotation set

set The returned list of pods should only returns pods from the specified namespace

The returned list of pods should observe the filtering and label selection criteria specified by metav1.ListOptions

Covering those use cases will give us a solid foundation to avoid regression when this function will get more complicated (usually that’s the evolution for successful piece of code).

Kubernetes Client Mock

Kubernetes offers a simple and powerful fake client that has a very efficient mechanism to simulate the desired output from a specific request, in our case clientset.CoreV1().Pods(namespace).List(listOpt) . You have to pass the slice of runtime.Object you desire when you create a new fake client. Awesome and easy.

clientset : fake . NewSimpleClientset ( & v1 . Pod { ObjectMeta : metav1 . ObjectMeta { Name : "influxdb-v2" , Namespace : "default" , Annotations : map [ string ] string {}, }, }, & v1 . Pod { ObjectMeta : metav1 . ObjectMeta { Name : "chronograf" , Namespace : "default" , Annotations : map [ string ] string {}, }, }),

For example this clientset will return two pods, one called influxdb-v2 and one called chronograf , but you can return what ever you need: Services, Deployments, Ingress, Custom Resource Definition or even a mix of everything.

In practice

I wrote a bunch of tests for kube-profefe that are using a fake client. You can get inspiration over there.

Conclusion