From 76deb2514072335e3c1b1d4d98db07dc5e905d92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bernhard=20Str=C3=A4hle?= Date: Sat, 12 Oct 2024 23:47:23 +0200 Subject: [PATCH] Add support for minItems and maxItems (#5836) --- .../crdv2/generator/AbstractJsonSchema.java | 55 ++++++++++++------- .../generator/KubernetesJSONSchemaProps.java | 4 ++ .../validation/ValidationSpec.java | 13 +++++ ...dations.samples.fabric8.io.v1.approved.yml | 19 +++++++ 4 files changed, 70 insertions(+), 21 deletions(-) diff --git a/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/AbstractJsonSchema.java b/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/AbstractJsonSchema.java index 6f29c5b7e94..1a0a3a3dee2 100644 --- a/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/AbstractJsonSchema.java +++ b/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/AbstractJsonSchema.java @@ -227,6 +227,8 @@ class PropertyMetadata { private String pattern; private Long minLength; private Long maxLength; + private Long minItems; + private Long maxItems; private boolean nullable; private String format; private List validationRules = new ArrayList<>(); @@ -248,26 +250,48 @@ public PropertyMetadata(JsonSchema value, BeanProperty beanProperty) { } if (value.isStringSchema()) { - System.out.println("String schema"); StringSchema stringSchema = value.asStringSchema(); // only set if ValidationSchemaFactoryWrapper is used - this.pattern = stringSchema.getPattern(); - this.maxLength = ofNullable(stringSchema.getMaxLength()) + pattern = ofNullable(stringSchema.getPattern()) + .or(() -> ofNullable(beanProperty.getAnnotation(Pattern.class)).map(Pattern::value)) + .orElse(null); + + maxLength = ofNullable(stringSchema.getMaxLength()) .map(Integer::longValue) .or(() -> ofNullable(beanProperty.getAnnotation(Size.class)) .map(Size::max) .filter(v -> v < Long.MAX_VALUE)) .orElse(null); - this.minLength = ofNullable(stringSchema.getMinLength()) + minLength = ofNullable(stringSchema.getMinLength()) .map(Integer::longValue) .or(() -> ofNullable(beanProperty.getAnnotation(Size.class)) .map(Size::min) .filter(v -> v > 0)) .orElse(null); - - } else { - // TODO: process the other schema types for validation values + } else if(value.isNumberSchema() || value.isIntegerSchema()){ + // minimum and maximum are only allowed on number and integer types + ofNullable(beanProperty.getAnnotation(Max.class)).ifPresent(a -> { + max = a.value(); + if (!a.inclusive()) { + exclusiveMaximum = true; + } + }); + ofNullable(beanProperty.getAnnotation(Min.class)).ifPresent(a -> { + min = a.value(); + if (!a.inclusive()) { + exclusiveMinimum = true; + } + }); + } else if (value.isArraySchema()) { + maxItems = ofNullable(beanProperty.getAnnotation(Size.class)) + .map(Size::max) + .filter(v -> v < Long.MAX_VALUE) + .orElse(null); + minItems = ofNullable(beanProperty.getAnnotation(Size.class)) + .map(Size::min) + .filter(v -> v > 0) + .orElse(null); } collectValidationRules(beanProperty, validationRules); @@ -276,23 +300,9 @@ public PropertyMetadata(JsonSchema value, BeanProperty beanProperty) { // see ValidationSchemaFactoryWrapper nullable = beanProperty.getAnnotation(Nullable.class) != null; - ofNullable(beanProperty.getAnnotation(Max.class)).ifPresent(a -> { - max = a.value(); - if (!a.inclusive()) { - exclusiveMaximum = true; - } - }); - ofNullable(beanProperty.getAnnotation(Min.class)).ifPresent(a -> { - min = a.value(); - if (!a.inclusive()) { - exclusiveMinimum = true; - } - }); - // TODO: should the following be deprecated? required = beanProperty.getAnnotation(Required.class) != null; defaultValue = ofNullable(beanProperty.getAnnotation(Default.class)).map(Default::value).orElse(defaultValue); - pattern = ofNullable(beanProperty.getAnnotation(Pattern.class)).map(Pattern::value).orElse(pattern); } public void updateSchema(T schema) { @@ -316,6 +326,9 @@ public void updateSchema(T schema) { schema.setMinLength(minLength); schema.setMaxLength(maxLength); + schema.setMinItems(minItems); + schema.setMaxItems(maxItems); + schema.setPattern(pattern); schema.setFormat(format); if (preserveUnknownFields) { diff --git a/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/KubernetesJSONSchemaProps.java b/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/KubernetesJSONSchemaProps.java index 496654f4d32..00b388bafab 100644 --- a/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/KubernetesJSONSchemaProps.java +++ b/crd-generator/api-v2/src/main/java/io/fabric8/crdv2/generator/KubernetesJSONSchemaProps.java @@ -42,6 +42,10 @@ public interface KubernetesJSONSchemaProps { void setMaxLength(Long max); + void setMinItems(Long min); + + void setMaxItems(Long max); + void setPattern(String pattern); void setFormat(String format); diff --git a/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/validation/ValidationSpec.java b/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/validation/ValidationSpec.java index 239abb8a8fc..ddbaf426e80 100644 --- a/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/validation/ValidationSpec.java +++ b/crd-generator/test/src/test/java/io/fabric8/crd/generator/approvaltests/validation/ValidationSpec.java @@ -21,6 +21,8 @@ import io.fabric8.generator.annotation.Size; import lombok.Data; +import java.util.List; + @Data public class ValidationSpec { @@ -33,6 +35,7 @@ public class ValidationSpec { private ValidationOnDouble onDouble; private ValidationOnDoublePrim onDoublePrim; private ValidationOnString onString; + private ValidationOnList onList; @Data static class ValidationOnInteger { @@ -191,4 +194,14 @@ static class ValidationOnString { private String minLength1maxLength3; } + @Data + static class ValidationOnList { + @Size(min = 1) + private List minItems1; + @Size(max = 1) + private List maxItems1; + @Size(min = 1, max = 3) + private List minItems1maxItems3; + } + } diff --git a/crd-generator/test/src/test/resources/io/fabric8/crd/generator/approvaltests/CRDGeneratorApprovalTest.approvalTest.validations.samples.fabric8.io.v1.approved.yml b/crd-generator/test/src/test/resources/io/fabric8/crd/generator/approvaltests/CRDGeneratorApprovalTest.approvalTest.validations.samples.fabric8.io.v1.approved.yml index de18a96b5d3..9c60c4183f4 100644 --- a/crd-generator/test/src/test/resources/io/fabric8/crd/generator/approvaltests/CRDGeneratorApprovalTest.approvalTest.validations.samples.fabric8.io.v1.approved.yml +++ b/crd-generator/test/src/test/resources/io/fabric8/crd/generator/approvaltests/CRDGeneratorApprovalTest.approvalTest.validations.samples.fabric8.io.v1.approved.yml @@ -179,6 +179,25 @@ spec: minimum: 1.0 type: "integer" type: "object" + onList: + properties: + maxItems1: + items: + type: "string" + maxItems: 1 + type: "array" + minItems1: + items: + type: "string" + minItems: 1 + type: "array" + minItems1maxItems3: + items: + type: "string" + maxItems: 3 + minItems: 1 + type: "array" + type: "object" onLong: properties: maximum1: