Kubernetes applications can be written with the Go language using the client-go library: https://github.com/kubernetes/client-go. This library provides tools to test apps written with it. Let’s explore these tools.

You can get the complete sources of this post on a dedicated github repository: https://github.com/feloy/testing-k8s-go-apps

The kubernetes package

Let’s first examine the kubernetes package, providing the NewForConfig method used to create a new Clientset object, needed to connect to the Kubernetes cluster.

The Clientset type implements the Interface interface defined in the same package and all methods of this type belongs to this interface. So, one can create another implementation of this interface to replace the real one.

Thanks to the client-go developers, they have done this work within the kubernetes/fake package. This package provides a new fake.Clientset type also implementing this interface. This package also provides a NewSimpleClientset method that can be used to create a fake clientset that will be very useful for testing our applications.

Use the Interface , Luke!

To test your application, you will have to use the real (from the kubernetes package) Clientset for your application, and the fake (from the kubernetes.fake package) one for your tests.

For this reason, you will have to always declare your methods working with Clientset to use the Interface type instead. So you will be able to use any implementation, depending on you are in the application or in the tests.

In our example, we create a k8s structure containing a clientset field of type kubernetes.Interface .

Getting the server version

We can now start to use the clientset to work with our Kubernetes cluster. First of all, let’s write a method that gets the version of the Kubernetes server. Here is the complete implementation:

If you can access a Kubernetes cluster and have the corresponding config file in your .kube path, you can try and run your app:

$ go run main.go

v1.9.2

and testing it

We now have to test our getVersion method. For this, we first have to create an instance of the k8s structure containing a fake implementation of a clientset instead of a real one, with the help of the NewSimpleClientset method. We can then call the getVersion method on this fake instance and get the version returned by our fake kubernetes cluster, which will always return the same default value.

Verifying the server version

We can now write a more advanced method that will verify that the cluster server is of an expected version:

and testing it

To test it, we will have to change the version value returned by the fake clientset. For this, we see that the fake Discovery implementation exposes a FakedServerVersion field that we can modify. Thanks to this facility, we are able to test all the cases of our isVersion method:

Creation, Reaction!

In some cases, we would like that our fake cluster reacts when we make some operation on it. For example, if we need to verify that the user can create some deployment on the cluster, we will have to create some SelfSubjectAccessReview (SSAR) and examine its status. When we create such a SSAR, a real Kubernetes cluster will update its status with the corresponding value. A fake cluster won’t do it, but we can make it ourselves.

Can I?

Here is a new method that determines if the user running the app can create deployments, using SelfSubjectAccessReview :

and testing it

we will first try to test this method with a NewSimpleClientset , as before. In this case, the SSAR we have created is not updated, and its Status is always false. This value covers the case when we want to test that the user does not have the authorization to create deployments, but not other cases.

The Fake type in the testing package

If we look at the content of the fake.Clientset type, we can see it embeds the testing.Fake type. This type implements the client.Interface interface, and especially exposes an AddReactor method, useful to react on some operations. Here is its signature:

The AddReactor method first gets two parameters verb and resource which describe the operation on which we want to react. For example on create ’ing a SelfSubjectAccessReview . The method then gets a latest parameter reaction which is a method that will be executed on this operation. This reaction method returns an handled value indicating if this reactor has effectively handled the case, a ret object which will replace the original object and an err in the case we want to simulate an error during the operation.

With these reactors, we can now handle the two latest cases, where the user can create a deployment or when the creation of an SSAR raises an error.

Conclusion

With these simple methods, you should be able to begin and test you Kubernetes applications written in Go.

I would really appreciate any comment on these first methods, and any link to other ones — I would complete this article as soon as I discover news ones.