Skip to content

Latest commit

 

History

History
275 lines (220 loc) · 7.65 KB

CRD-generator.md

File metadata and controls

275 lines (220 loc) · 7.65 KB

CRD generation

Quick start

Import the Annotation Processor into your build.

with Maven:

<dependency>
    <groupId>io.fabric8</groupId>
    <artifactId>crd-generator-apt</artifactId>
    <scope>provided</scope>
</dependency>

with Gradle:

dependencies {
    annotationProcessor 'io.fabric8:crd-generator-apt:<version>'
    ...
}

Now you can define a class that extends io.fabric8.kubernetes.client.CustomResource and the corresponding CRD is generated in the folder: target/classes/META-INF/fabric8

For example, for code similar to:

@Group("org.example")
@Version("v1alpha1")
@ShortNames("ex")
public class Example extends CustomResource<ExampleSpec, ExampleStatus> implements Namespaced {}

public class ExampleSpec {
  int someValue;
}

public class ExampleStatus {
  boolean error;
  String message;
}

Running the compile task will generate 2 files target/classes/META-INF/fabric8/examples.org.example-v1.yml and target/classes/META-INF/fabric8/examples.org.example-v1beta1.yml, the file name is calculated as <plural>.<group>-<CRD spec version>.yml.

The content of the v1 looks similar to:

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: examples.org.example
spec:
  group: org.example
  names:
    kind: Example
    plural: examples
    shortNames:
    - ex
    singular: example
  scope: Namespaced
  versions:
  - name: v1alpha1
    schema:
      openAPIV3Schema:
        properties:
          spec:
            properties:
              someValue:
                type: integer
            type: object
          status:
            properties:
              error:
                type: boolean
              message:
                type: string
            type: object
        type: object
    served: true
    storage: true
    subresources:
      status: {}

Features

com.fasterxml.jackson.annotation.JsonProperty

If a field or one of its accessors is annotated with com.fasterxml.jackson.annotation.JsonProperty

public class ExampleSpec {
  @JsonProperty("myValue")
  int someValue;
}

The generated field in the CRD will be named after the value provided in the annotation instead of using the default name derived from the field name, such as:

          spec:
            properties:
              myValue:
                type: integer
            type: object

com.fasterxml.jackson.annotation.JsonPropertyDescription

If a field or one of its accessors is annotated with com.fasterxml.jackson.annotation.JsonPropertyDescription

public class ExampleSpec {
  @JsonPropertyDescription("This is some value")
  int someValue;
}

The generated field in the CRD will preserve the provided description, such as:

          spec:
            properties:
              someValue:
                description: This is some value
                type: integer
            type: object

com.fasterxml.jackson.annotation.JsonIgnore

If a field or one of its accessors is annotated with com.fasterxml.jackson.annotation.JsonIgnore

public class ExampleSpec {
  @JsonIgnore
  int someValue;
}

The field will be skipped in the generated CRD and will not appear in the schema for this type, such as:

          spec:
            type: object

javax.validation.constraints.NotNull

If a field or one of its accessors is annotated with javax.validation.constraints.NotNull

public class ExampleSpec {
  @NotNull
  int someValue;
}

The field will be marked as required in the generated CRD, such as:

          spec:
            properties:
              someValue:
                type: integer
            required:
            - someValue
            type: object

io.fabric8.crd.generator.annotation.SchemaFrom

If a field or one of its accessors is annotated with io.fabric8.crd.generator.annotation.SchemaFrom

public class ExampleSpec {
  @SchemaFrom(ExampleStatus.class)
  int someValue;
}

The CRD generator will substitute the default type inferred from the field and replace it by the computed schema associated with the Java class provided as a value of the SchemaFrom annotation, as seen below, where ExampleStatus is the class defined in the example above:

          spec:
            properties:
              someValue:
                properties:
                  error:
                    type: boolean
                  message:
                    type: string
                type: object
            type: object

io.fabric8.crd.generator.annotation.SchemaSwap

If a class is annotated with io.fabric8.crd.generator.annotation.SchemaSwap

@SchemaSwap(originalType = ExampleSpec.class, fieldName = "someValue", targetType = ExampleStatus.class)
public class Example extends CustomResource<ExampleSpec, ExampleStatus> implements Namespaced {}

The CRD generator will perform the same substitution as a SchemaFrom annotation with value equal to targetType was placed on the field named fieldName in the originalType class:

          spec:
            properties:
              someValue:
                properties:
                  error:
                    type: boolean
                  message:
                    type: string
                type: object
            type: object

Generating x-kubernetes-preserve-unknown-fields: true

If a field or one of its accessors is annotated with com.fasterxml.jackson.annotation.JsonAnyGetter/com.fasterxml.jackson.annotation.JsonAnySetter or the field type is com.fasterxml.jackson.databind.JsonNode

public class ExampleSpec {
  JsonNode someValue;

  @JsonAnyGetter
  JsonNode getSomeValue() {
    return someValue;
  }

  @JsonAnySetter
  void setSomeValue(JsonNode value) {
    this.someValue = value;
  }
}

Corresponding x-kubernetes-preserve-unknown-fields: true will be generated in the output CRD, such as:

          spec:
            properties:
              someValue:
                type: object
                x-kubernetes-preserve-unknown-fields: true
            type: object
            x-kubernetes-preserve-unknown-fields: true

Features cheatsheet

Annotation Description
com.fasterxml.jackson.annotation.JsonProperty The field is named after the provided value instead of looking up the java field name
com.fasterxml.jackson.annotation.JsonPropertyDescription The provided text is be embedded in the description of the field
com.fasterxml.jackson.annotation.JsonIgnore The field is ignored
com.fasterxml.jackson.annotation.JsonAnyGetter The corresponding object have x-kubernetes-preserve-unknown-fields: true defined
com.fasterxml.jackson.annotation.JsonAnySetter The corresponding object have x-kubernetes-preserve-unknown-fields: true defined
javax.validation.constraints.NotNull The field is marked as required
io.fabric8.crd.generator.annotation.SchemaFrom The field type for the generation is the one coming from the annotation
io.fabric8.crd.generator.annotation.SchemaSwap Same as SchemaFrom, but can be applied at any point in the class hierarchy

A field of type com.fasterxml.jackson.databind.JsonNode is encoded as an empty object with x-kubernetes-preserve-unknown-fields: true defined.