I've had to program against Kubernetes a lot in the last few years and there were many times where I could find almost no documentation, examples, or explanations around the work I needed to do. It is these areas of work that I will be writing about in hopes of spreading the knowledge I found so hard to sometimes obtain. This will be a multipart series so lets first focus on how you would apply objects into Kubernetes in a generic fashion.
First let's stub out what our method will look like. The meat of our method's input is the slice of resources it takes. Our resource type will hold a handful of key fields. Our resource type will hold information parsed from manifests given to us, just like how you would use kubectl apply. Now that we've defined our type to hold a resource parsed from a manifest we can fill out our method completely. Notice that there's support for handling updates to existing resources here. This will be covered in more detail in part 2 so for now lets focus on the part that creates something new. The method looks fairly simple at this point, but don't let that fool you. The real chunk of this work comes from parsing a manifest (YAML) and converting each document in that manifest into a resource.
Parsing documents out of a manifest is the first thing we need to do here. Once we are able to return back a slice of documents we can then turn each document into a resource which we've defined above. At the time the Kubernetes libraries did things very differently than what we wanted to do. Manifests were converted from YAML to JSON, then parsed into structs. We wanted to parse the YAML directly. There is a much faster way to do this without using regular expressions which I had started off with, but the code was much more messy, complex, and harder to follow. Note that the original way I had gone with was roughly 100x faster when we benchmarked it so if you require more performance in this area I urge you not to use regular expressions.
Now that we are able to work with documents from a manifest we can focus on converting them into resources. There are three key things we need to do:
We can lean on the Kubernetes libraries to decode a document into an unstructured. Searching is straightforward, we just need to work with the unstructured APIs. Providing the REST mapping is the last piece.
Now that we have all of the required pieces built out we can put it all together. That's it! You now have a fully functioning, dynamic kubernetes object applier.
In part 2 we will look at the handling updates as part of our apply logic. We will cover the edge cases that need to be handled, especially the ones that are not so obvious or documented.