/k8s-objects-generator

CLI tool that generates Kubernetes Go types that can be used with TinyGo starting from the official OpenAPI spec

Primary LanguageGoApache License 2.0Apache-2.0

Stable

This repository provides the CLI tool k8s-objects-generator.

The purpose of this tool is to process the OpenAPI file provided by Kubernetes and generate models for all the types defined inside of it.

The Go models created by this project are compatible with TinyGo and can be serialized and deserialized using the JSON format.

Note: this tool is useless for regular users of Kubewarden. If you just want to use Kubernetes objects inside of a TinyGo program, just consume the files generated by this tool.

You can find them inside of the github.com/kubewarden/k8s-objects module.

Background information

TinyGo is an alternative Go compiler that can produce WebAssembly code that is not targeting the browser. The official Go compiler isn't capable of that yet. TinyGo is the only option for developers who want to write Go code and build it into a WebAssembly module meant to be run outside of the browser.

TinyGo doesn't yet support the full Go Standard Library, plus it has limited support of Go reflection. Because of that, it is not possible to import the official Kubernetes Go library from upstream (e.g.: k8s.io/api/core/v1). Importing these official Kubernetes types will result in a compilation failure.

Technical details

This section describes how k8s-objects-generator solves the problems that prevent the usage of the official Kubernetes Go library with TinyGo.

Solving the compilation errors

The Go types defined inside of the official Kubernetes library have a series of methods that perform operations such as validating the object.

These methods are the ones that rely on pieces of the Go Standard Library and on 3rd party libraries that are not compatible with the WebAssembly target.

The good news is that, for the Kubewarden scenario, we don't care about these extra methods. We only need vanilla Go types that all the Kubernetes resources.

The k8s-objects-generator leverages go-swagger to process the official swagger.json file provided by Kubernetes and create all the models defined inside of it. These models are created using a custom template of go-swagger that just writes objects definitions.

However, the models generated by go-swagger include some data types that are not defined by the Go standard library. That includes types to handle base64-encoded bytes and datetime objects.

All these custom data types are provided by the github.com/go-openapi/strfmt module. Unfortunately this module includes some dependencies that do not compile when using TinyGo.

Luckily, these dependencies are required only when implementing the validation methods that we do not care about.

To solve this issue, a stripped down version of the github.com/go-openapi/strfmt library has been created here: github.com/kubewarden/strfmt.

The go.mod file generated by k8s-objects-generator features a replace directive that substitutes the usage of the github.com/go-openapi/strfmt with github.com/kubewarden/strfmt.

Solving the "flat" package problem

By default, swagger generates all the Kubernetes objects inside of the same Go package. That means you would end up with more than 560 Go types defined inside of the same directory and that objects would have names like IoK8sAPICoreV1Pod or IoK8sApimachineryPkgApisMetaV1ObjectMeta.

The k8s-objects-generator solves this problem by splitting the big swagger file provided by Kubernetes developers into smaller ones. The tool creates one swagger file per package. The final code will have the same package structure of the official Kubernetes Go libraries.

During the split operation, the OpenAPI definitions are partially rewritten to ensure the final objects can resolve each others.

Requirements

The swagger CLI tool from the go-swagger project must be installed.

Consuming the types generated by this project requires TinyGo 0.28.1 or later.

Warning Using an older version of TinyGo will result in runtime errors due to the limited support for Go reflection.

swagger 0.29.0 or later should be installed

Usage

Obtain the swagger.json file from Kubernetes upstream repository

Invoke the following command:

k8s-objects-generator -f swagger.json -o ~/k8s-data-types

This command reads the swagger file referenced by the -f flag and creates all the files inside of the ~/k8s-data-types directory.

Output directory layout

The output directory provided via the -o flag will have the following structure:

~/k8s-data-types
|
\-- src
    |
    \-- github.com
        |
        \-- kubewarden
            |
            \-- k8s-objects

k8s-objects-generator will invoke the go binary using ~/k8s-data-types as exclusive GOPATH. That means that, by the end of the process, the output directory will feature also pkg and other src directories.

The relevant files are going to be stored inside of the ~/k8s-data-types/src/github.com/kubewarden/k8s-objects directory. This is the only directory you need to preserve.

Note: the name of the final Git repository can be changed using the -repo flag.

Pushing new versions to kubewarden/k8s-objects

Set KUBERNETES_VERSION_MIN, KUBERNETES_VERSION_MAX in mass-generate.sh, KUBEMINOR in mass-push.sh as needed.

Delete and reclone kubewarden/k8s-objects. In my case:

cd suse/kw
rm k8s-objects; git clone git@github.com:kubewarden/k8s-objects.git

Generate all files for all k8s versions, each on its own branch:

./mass-generate.sh -m commit.md --git-dir ~/suse/kw/k8s-objects

Now, push to upstream kubewarden/k8s-objects as needed. You can either push the new branch for the new k8s release (e.g: 1.30):

cd ~/suse/kw/k8s-objects
git push origin release-1.30
git push origin v1.30.0-kw1

Or do a mass push, potentially overwritting old branches:

mv ~/suse/kw/k8s-objects ~/hacking/kubernetes/kubewarden/k8s-objects
./mass-push.sh -m commit.md --git-dir ~/suse/kw/k8s-objects