Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

backport additional crd-generator annotations #128

Merged
merged 2 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .blazar.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ enabled: true
env:
SET_VERSION_OVERRIDE: $GIT_BRANCH-SNAPSHOT
MAVEN_OPTS: -Xmx4096m
MAVEN_ARGS: -DskipTests -am -pl kubernetes-server-mock,kubernetes-model-generator,kubernetes-model-generator/kubernetes-model-apiextensions,kubernetes-client,crd-generator/api,crd-generator/apt
MAVEN_ARGS: -DskipTests -am -pl kubernetes-server-mock,kubernetes-model-generator,kubernetes-model-generator/kubernetes-model-apiextensions,kubernetes-client,crd-generator/api,crd-generator/apt,generator-annotations

buildResources:
cpus: 2
Expand Down
5 changes: 5 additions & 0 deletions crd-generator/api/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,11 @@
<scope>compile</scope>
</dependency>

<dependency>
<groupId>io.fabric8</groupId>
<artifactId>generator-annotations</artifactId>
</dependency>

<dependency>
<groupId>io.fabric8</groupId>
<artifactId>kubernetes-model-common</artifactId>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import io.fabric8.crd.generator.annotation.SchemaSwap;
import io.fabric8.crd.generator.utils.Types;
import io.fabric8.kubernetes.api.model.Duration;
import io.fabric8.kubernetes.api.model.IntOrString;
Expand Down Expand Up @@ -65,6 +64,8 @@ public abstract class AbstractJsonSchema<T, B> {
protected static final TypeDef DATE = TypeDef.forName(Date.class.getName());
protected static final TypeRef DATE_REF = DATE.toReference();

private static final String VALUE = "value";

private static final String INT_OR_STRING_MARKER = "int_or_string";
private static final String STRING_MARKER = "string";
private static final String INTEGER_MARKER = "integer";
Expand All @@ -83,6 +84,11 @@ public abstract class AbstractJsonSchema<T, B> {
public static final String ANNOTATION_JSON_IGNORE = "com.fasterxml.jackson.annotation.JsonIgnore";
public static final String ANNOTATION_JSON_ANY_GETTER = "com.fasterxml.jackson.annotation.JsonAnyGetter";
public static final String ANNOTATION_JSON_ANY_SETTER = "com.fasterxml.jackson.annotation.JsonAnySetter";
public static final String ANNOTATION_MIN = "io.fabric8.generator.annotation.Min";
public static final String ANNOTATION_MAX = "io.fabric8.generator.annotation.Max";
public static final String ANNOTATION_PATTERN = "io.fabric8.generator.annotation.Pattern";
public static final String ANNOTATION_NULLABLE = "io.fabric8.generator.annotation.Nullable";
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_SCHEMA_SWAP = "io.fabric8.crd.generator.annotation.SchemaSwap";
Expand Down Expand Up @@ -115,6 +121,51 @@ public static String getSchemaTypeFor(TypeRef typeRef) {
return type;
}

protected static class SchemaPropsOptions {
final Optional<Double> min;
final Optional<Double> max;
final Optional<String> pattern;
final boolean nullable;
final boolean required;

SchemaPropsOptions() {
min = Optional.empty();
max = Optional.empty();
pattern = Optional.empty();
nullable = false;
required = false;
}

public SchemaPropsOptions(Optional<Double> min, Optional<Double> max, Optional<String> pattern,
boolean nullable, boolean required) {
this.min = min;
this.max = max;
this.pattern = pattern;
this.nullable = nullable;
this.required = required;
}

public Optional<Double> getMin() {
return min;
}

public Optional<Double> getMax() {
return max;
}

public Optional<String> getPattern() {
return pattern;
}

public boolean isNullable() {
return nullable;
}

public boolean getRequired() {
return nullable;
}
}

/**
* Creates the JSON schema for the particular {@link TypeDef}. This is template method where
* sub-classes are supposed to provide specific implementations of abstract methods.
Expand Down Expand Up @@ -269,7 +320,15 @@ private T internalFromImpl(TypeDef definition, Set<String> visited, List<Interna
} else {
possiblyUpdatedSchema = addDescription(schema, description);
}
addProperty(possiblyRenamedProperty, builder, possiblyUpdatedSchema);

SchemaPropsOptions options = new SchemaPropsOptions(
facade.min,
facade.max,
facade.pattern,
facade.nullable,
facade.required);

addProperty(possiblyRenamedProperty, builder, possiblyUpdatedSchema, options);
}

validateRemainingSchemaSwaps("unmatched field", currentSchemaSwaps.stream().collect(Collectors.toList()));
Expand All @@ -292,6 +351,10 @@ private static class PropertyOrAccessor {
private final String propertyName;
private final String type;
private String renamedTo;
private Optional<Double> min;
private Optional<Double> max;
private Optional<String> pattern;
private boolean nullable;
private boolean required;
private boolean ignored;
private boolean preserveUnknownFields;
Expand All @@ -303,6 +366,10 @@ private PropertyOrAccessor(Collection<AnnotationRef> annotations, String name, S
this.name = name;
this.propertyName = propertyName;
type = isMethod ? "accessor" : "field";

min = Optional.empty();
max = Optional.empty();
pattern = Optional.empty();
}

static PropertyOrAccessor fromProperty(Property property) {
Expand All @@ -316,17 +383,34 @@ static PropertyOrAccessor fromMethod(Method method, String propertyName) {
public void process() {
annotations.forEach(a -> {
switch (a.getClassRef().getFullyQualifiedName()) {
case ANNOTATION_NULLABLE:
nullable = true;
break;
case ANNOTATION_MAX:
max = Optional.of((Double) a.getParameters().get(VALUE));
break;
case ANNOTATION_MIN:
min = Optional.of((Double) a.getParameters().get(VALUE));
break;
case ANNOTATION_PATTERN:
pattern = Optional.of((String) a.getParameters().get(VALUE));
break;
case ANNOTATION_NOT_NULL:
LOGGER.warn("Annotation: {} on property: {} is deprecated. Please use: {} instead", ANNOTATION_NOT_NULL, name,
ANNOTATION_REQUIRED);
required = true;
break;
case ANNOTATION_REQUIRED:
required = true;
break;
case ANNOTATION_JSON_PROPERTY:
final String nameFromAnnotation = (String) a.getParameters().get("value");
final String nameFromAnnotation = (String) a.getParameters().get(VALUE);
if (!Strings.isNullOrEmpty(nameFromAnnotation) && !propertyName.equals(nameFromAnnotation)) {
renamedTo = nameFromAnnotation;
}
break;
case ANNOTATION_JSON_PROPERTY_DESCRIPTION:
final String descriptionFromAnnotation = (String) a.getParameters().get("value");
final String descriptionFromAnnotation = (String) a.getParameters().get(VALUE);
if (!Strings.isNullOrEmpty(descriptionFromAnnotation)) {
description = descriptionFromAnnotation;
}
Expand All @@ -349,6 +433,22 @@ public String getRenamedTo() {
return renamedTo;
}

public boolean isNullable() {
return nullable;
}

public Optional<Double> getMax() {
return max;
}

public Optional<Double> getMin() {
return min;
}

public Optional<String> getPattern() {
return pattern;
}

public boolean isRequired() {
return required;
}
Expand Down Expand Up @@ -393,6 +493,10 @@ private static class PropertyFacade {
private final Set<InternalSchemaSwap> matchedSchemaSwaps;
private String renamedTo;
private String description;
private Optional<Double> min;
private Optional<Double> max;
private Optional<String> pattern;
private boolean nullable;
private boolean required;
private boolean ignored;
private boolean preserveUnknownFields;
Expand Down Expand Up @@ -420,6 +524,9 @@ public PropertyFacade(Property property, Map<String, Method> potentialAccessors,
if (method != null) {
propertyOrAccessors.add(PropertyOrAccessor.fromMethod(method, name));
}
min = Optional.empty();
max = Optional.empty();
pattern = Optional.empty();
}

public Property process() {
Expand Down Expand Up @@ -456,6 +563,22 @@ public Property process() {
}
}

if (p.getMin().isPresent()) {
min = p.getMin();
}

if (p.getMax().isPresent()) {
max = p.getMax();
}

if (p.getPattern().isPresent()) {
pattern = p.getPattern();
}

if (p.isNullable()) {
nullable = true;
}

if (p.isRequired()) {
required = true;
} else if (p.isIgnored()) {
Expand Down Expand Up @@ -526,7 +649,7 @@ private String extractUpdatedNameFromJacksonPropertyIfPresent(Property property)
* @param builder the builder representing the schema being built
* @param schema the built schema for the property being added
*/
public abstract void addProperty(Property property, B builder, T schema);
public abstract void addProperty(Property property, B builder, T schema, SchemaPropsOptions options);

/**
* Finishes up the process by actually building the final JSON schema based on the provided
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@

import java.lang.annotation.*;

@Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD})
/*
* Used to tweak the behavior of the crd-generator
*/
@Target({ ElementType.ANNOTATION_TYPE, ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface SchemaFrom {
Class<?> type() default void.class;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,15 @@

import java.lang.annotation.*;

@Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE_USE, ElementType.TYPE})
/*
* Used to tweak the behavior of the crd-generator
*/
@Target({ ElementType.ANNOTATION_TYPE, ElementType.TYPE_USE, ElementType.TYPE })
@Retention(RetentionPolicy.RUNTIME)
public @interface SchemaSwap {
Class<?> originalType();

String fieldName();

Class<?> targetType() default void.class;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,19 @@
import io.sundr.model.Property;
import io.sundr.model.TypeDef;
import io.sundr.model.TypeRef;

import java.util.List;

public class JsonSchema extends AbstractJsonSchema<JSONSchemaProps, JSONSchemaPropsBuilder> {

private static final JsonSchema instance = new JsonSchema();

private static final JSONSchemaProps JSON_SCHEMA_INT_OR_STRING = new JSONSchemaPropsBuilder()
.withXKubernetesIntOrString(true)
.withAnyOf(
new JSONSchemaPropsBuilder().withType("integer").build(),
new JSONSchemaPropsBuilder().withType("string").build())
.build();
.withXKubernetesIntOrString(true)
.withAnyOf(
new JSONSchemaPropsBuilder().withType("integer").build(),
new JSONSchemaPropsBuilder().withType("string").build())
.build();

/**
* Creates the JSON schema for the particular {@link TypeDef}.
Expand All @@ -55,8 +56,16 @@ public JSONSchemaPropsBuilder newBuilder() {

@Override
public void addProperty(Property property, JSONSchemaPropsBuilder builder,
JSONSchemaProps schema) {
JSONSchemaProps schema, SchemaPropsOptions options) {
if (schema != null) {
options.getMin().ifPresent(schema::setMinimum);
options.getMax().ifPresent(schema::setMaximum);
options.getPattern().ifPresent(schema::setPattern);

if (options.isNullable()) {
schema.setNullable(true);
}

builder.addToProperties(property.getName(), schema);
}
}
Expand All @@ -73,21 +82,21 @@ public JSONSchemaProps build(JSONSchemaPropsBuilder builder, List<String> requir
@Override
protected JSONSchemaProps arrayLikeProperty(JSONSchemaProps schema) {
return new JSONSchemaPropsBuilder()
.withType("array")
.withNewItems()
.withSchema(schema)
.and()
.build();
.withType("array")
.withNewItems()
.withSchema(schema)
.and()
.build();
}

@Override
protected JSONSchemaProps mapLikeProperty(JSONSchemaProps schema) {
return new JSONSchemaPropsBuilder()
.withType("object")
.withNewAdditionalProperties()
.withSchema(schema)
.endAdditionalProperties()
.build();
.withType("object")
.withNewAdditionalProperties()
.withSchema(schema)
.endAdditionalProperties()
.build();
}

@Override
Expand All @@ -108,7 +117,7 @@ protected JSONSchemaProps enumProperty(JsonNode... enumValues) {
@Override
protected JSONSchemaProps addDescription(JSONSchemaProps schema, String description) {
return new JSONSchemaPropsBuilder(schema)
.withDescription(description)
.build();
.withDescription(description)
.build();
}
}
Loading
Loading