diff --git a/CHANGELOG.md b/CHANGELOG.md index 5e76312e895..4548ed0fdaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * Fix #4383: bump snakeyaml from 1.30 to 1.31 #### New Features +* Feat: add annotation @PreserveUnknownFields for marking generated field have `x-kubernetes-preserve-unknown-fields: true` defined #### _**Note**_: Breaking changes in the API diff --git a/crd-generator/api/src/main/java/io/fabric8/crd/generator/AbstractJsonSchema.java b/crd-generator/api/src/main/java/io/fabric8/crd/generator/AbstractJsonSchema.java index 747ad6ad7c4..0c8b88906b3 100644 --- a/crd-generator/api/src/main/java/io/fabric8/crd/generator/AbstractJsonSchema.java +++ b/crd-generator/api/src/main/java/io/fabric8/crd/generator/AbstractJsonSchema.java @@ -86,6 +86,7 @@ public abstract class AbstractJsonSchema { public static final String ANNOTATION_REQUIRED = "io.fabric8.generator.annotation.Required"; public static final String ANNOTATION_NOT_NULL = "javax.validation.constraints.NotNull"; public static final String ANNOTATION_SCHEMA_FROM = "io.fabric8.crd.generator.annotation.SchemaFrom"; + public static final String ANNOTATION_PERSERVE_UNKNOWN_FIELDS = "io.fabric8.crd.generator.annotation.PreserveUnknownFields"; public static final String ANNOTATION_SCHEMA_SWAP = "io.fabric8.crd.generator.annotation.SchemaSwap"; public static final String JSON_NODE_TYPE = "com.fasterxml.jackson.databind.JsonNode"; @@ -123,21 +124,25 @@ protected static class SchemaPropsOptions { final boolean nullable; final boolean required; + final boolean preserveUnknownFields; + SchemaPropsOptions() { min = Optional.empty(); max = Optional.empty(); pattern = Optional.empty(); nullable = false; required = false; + preserveUnknownFields = false; } public SchemaPropsOptions(Optional min, Optional max, Optional pattern, - boolean nullable, boolean required) { + boolean nullable, boolean required, boolean preserveUnknownFields) { this.min = min; this.max = max; this.pattern = pattern; this.nullable = nullable; this.required = required; + this.preserveUnknownFields = preserveUnknownFields; } public Optional getMin() { @@ -159,6 +164,10 @@ public boolean isNullable() { public boolean getRequired() { return nullable; } + + public boolean isPreserveUnknownFields() { + return preserveUnknownFields; + } } /** @@ -321,7 +330,8 @@ private T internalFromImpl(TypeDef definition, Set visited, List barProps = bar.getProperties(); assertNotNull(barProps); + assertTrue(bar.getXKubernetesPreserveUnknownFields()); // you can change everything assertEquals("integer", barProps.get("BAZ").getType()); diff --git a/doc/CRD-generator.md b/doc/CRD-generator.md index 4275c1ae3df..fb822d3f428 100644 --- a/doc/CRD-generator.md +++ b/doc/CRD-generator.md @@ -357,21 +357,44 @@ Corresponding `x-kubernetes-preserve-unknown-fields: true` will be generated in x-kubernetes-preserve-unknown-fields: true ``` +You can also annotate a field with `io.fabric8.crd.generator.annotation.PreserveUnknownFields`: + +```java +interface ExampleInterface {} + +public class ExampleSpec { + @PreserveUnknownFields + ExampleInterface someValue; +} +``` + +will be generated as: + +```yaml + spec: + properties: + someValue: + type: object + x-kubernetes-preserve-unknown-fields: true + type: object +``` + ## 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 | -| `io.fabric8.generator.annotation.Min` | The field defines a validation `min` | -| `io.fabric8.generator.annotation.Max` | The field defines a validation `max` | -| `io.fabric8.generator.annotation.Pattern` | The field defines a validation `pattern` | -| `io.fabric8.generator.annotation.Nullable` | The field is marked as `nullable` | -| `io.fabric8.generator.annotation.Required` | 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 | +| 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 | +| `io.fabric8.crd.generator.annotation.PreserveUnknownFields` | The field have `x-kubernetes-preserve-unknown-fields: true` defined | +| `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 | +| `io.fabric8.generator.annotation.Min` | The field defines a validation `min` | +| `io.fabric8.generator.annotation.Max` | The field defines a validation `max` | +| `io.fabric8.generator.annotation.Pattern` | The field defines a validation `pattern` | +| `io.fabric8.generator.annotation.Nullable` | The field is marked as `nullable` | +| `io.fabric8.generator.annotation.Required` | 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.