Skip to content

CAPI json-schema generator, part of SovereignCloudStack/cluster-gen

License

Notifications You must be signed in to change notification settings

SovereignCloudStack/capi-jsgen

Introduction

The tool capi-jsgen creates json-schemas for cluster-API Clusters which reference a ClusterClass. The primary use-case for these schemas is to create UI-Forms out of it, but they can be used in other contexts as well.

Concept

The generic Cluster specification is merged with a ClusterClass to create a specialized version of the Cluster specification. The tailoring takes place by copying the variable schemas from a ClusterClass to the generic Cluster spec. Additional to that, capi-jsgen can set default values for the ClusterClass, the MachineDeployment class and the namespace. Most likely you do not want certain fields like .status or .metadata.gereration in your UI. It is possible to remove or customize this by changing the "base schema". This is the schema that capi-jsgen works on to create specialized cluster-schemas. If you want to create a custom baseschema have a look at the baseschema-builder it contains a good starting point to create your custom baseschema.

     generic cluster-spec
+-----------------------------+
|apiVersion: cluster.x-k8s.io |          
|kind: Cluster                |                 specialized cluster-spec
|spec:                        |----+        +-----------------------------+
|  topology:                  |    |        |apiVersion: cluster.x-k8s.io |
|    variables: <[]Object>    |    |        |kind: Cluster                |
+-----------------------------+    |        |spec:                        |
                                   |        |  topology:                  |
                                   |        |    class: example-cc        |
                                   +------->|    variables:               |
                                   |        |      - name var1            |
     specific clusterclass         |        |        schema: sc1          |
+-----------------------------+    |        |      - name var2            |
|apiVersion: cluster.x-k8s.io |    |        |        schema: sc2          |
|kind: ClusterClass           |    |        +-----------------------------+
|name: example-cc             |    |        
|spec:                        |    |     
|  variables:                 |----+     
|    - name: var1             |          
|      schema: sc1            |          
|    - name: var2             |          
|      schema: sc2            |          
+-----------------------------+

Notice that the above graphic recklessly mixes specification (Cluster) and instances (ClusterClass). It is not correct in every detail and only meant to get a quick idea of the concept.

Usage

Usage of ./capi-jsgen:
  -baseschema string
        path to baseschema file (default "data/baseschema.json")
  -cache string
        Duration how long API-responses are cached (default "1h")
  -default-clusterclass
        When set, the clusterclass is used as default for .spec.topology.class (default true)
  -default-machineclass
        When set, the clusterclass name is used as default for .spec.topology.workers.machineDeployments.class (default true)
  -default-namespace
        When set, the namespace of the clusterclass is used as default for .metadata.namespace (default true)
  -listen string
        listen address (default ":8080")
  -local
        run in local mode
  -required
        only include required variables into the schema

Helm-Chart

API

There are two API endpoints that can be consumed. The first one offers information about the namespaces and the offered cluster-classes in the cluster. The second API offers Cluster schemas that are specific for a clusterclass in a namespace.

GET /clusterclasses

GET /clusterschema/{namespace}/{clusterclass}

Background

Kubernetes stores structured objects (resources) in its database. Before saving a new resource to its database, the kubernetes-apiserver validates whether the resource adheres to a certain structure. You can describe the desired structure (schema) for a kubernetes resource using kubectl explain. If you do so, kubectl retrieves the corresponding schema from the kubernetes-apiserver under <server>/openapi/v3. The format of this schema is json-schema, a standard to describe the validity of a structured object. This schema can be used to generate documentation, display a help-text (kubectl explain), generate a GUI or validate whether an object adheres to the required structure in the schema.

If a resource is validated by the schema this is only a necessary condition for it to be accepted by the kubernetes-apiserver. The schema validation alone is not sufficient to guarantee that the resource is accepted by the kubernetes-apiserver. For example, there can be webhooks that impose additional, stricter requirements upon the structure of the resource.

cluster-API is an extension to the kubernetes-apiserver. It introduces several new resource definitions (CRDs). The purpose of those CRDs is to define the schema of resources that are used to define kubernetes clusters. An important, central schema is called Cluster. It can be used in two ways (simplified):

  1. manually set all required values
  2. use a templating mechanism called ClusterClass and only feed variables to customize the output of the template

Both approaches use the same schema. The part in the schema (subschema) that defines the format of the variables is loosely defined. Basically, it accepts arbitrary key-value pairs. This makes sense because this schema has to validate all thinkable instances of Cluster, no matter which variables are used by a ClusterClass or if a ClusterClass is used at all.

The loose definition of the variables makes the generic Cluster schema a bad choice for creating a form or validating if a Cluster adheres to the required variables in a specific ClusterClass. The validation process for a Cluster that uses a ClusterClass is as follows:

  1. Read the referenced ClusterClass from .spec.topology.class from the Cluster resource.
  2. Use the referenced ClusterClass obtained in the prior step to read the variables and their schemas from .status.variables
  3. Validate all variables set in the Cluster resource under .spec.topology.variables against the variable schemas obtained in the prior step

capi-jsgen creates a concrete schema out of the generic Cluster schema and the variables of a concrete ClusterClass by embedding the variable schemas of the ClusterClass into the Cluster schema.

Limitations

  • only inline Patches work (no Runtime-SDK support), but configurable behaviour for definitionsConflict: true is planned
  • CEL is not supported, probably as long as it is not part of json-schema

Glossary

resource

A kubernetes object. Its structure can be validated by its schema.

schema

A description of the structure of an object.

subschema

A description of a part of the structure of an object. Part of a schema.