An open API service indexing awesome lists of open source software.

https://github.com/kubewarden/k8s-objects-generator

CLI tool that generates Kubernetes Go types that can be used with TinyGo starting from the official OpenAPI spec
https://github.com/kubewarden/k8s-objects-generator

hacktoberfest kubernetes kubernetes-security policy-as-code webassembly

Last synced: 6 months ago
JSON representation

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

Awesome Lists containing this project

README

        

[![Stable](https://img.shields.io/badge/status-stable-brightgreen?style=for-the-badge)](https://github.com/kubewarden/community/blob/main/REPOSITORIES.md#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](https://tinygo.org/)
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`](https://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](https://goswagger.io/) 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`](https://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`](https://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](https://goswagger.io/install.html) 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`](https://github.com/kubernetes/kubernetes/blob/release-1.24/api/openapi-spec/swagger.json)
file from Kubernetes [upstream repository](https://github.com/kubernetes/kubernetes/tree/release-1.24/api/openapi-spec)

Invoke the following command:

```console
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:

```console
cd suse/kw
rm k8s-objects; git clone [email protected]:kubewarden/k8s-objects.git
```

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

```console
./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):

```console
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:

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