Skip to content

Commit ecf2f9a

Browse files
authored
Allow having CEL validation rules only for specific CRD API versions (#11851)
Signed-off-by: Jakub Scholz <www@scholzj.com>
1 parent b99de9f commit ecf2f9a

6 files changed

Lines changed: 48 additions & 30 deletions

File tree

crd-generator/src/main/java/io/strimzi/crdgenerator/CrdGenerator.java

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.lang.reflect.ParameterizedType;
4646
import java.nio.charset.StandardCharsets;
4747
import java.nio.file.Files;
48+
import java.util.ArrayList;
4849
import java.util.Arrays;
4950
import java.util.Base64;
5051
import java.util.Collection;
@@ -820,7 +821,7 @@ && isMapOfTypes(propertyType, String.class, Quantity.class)) {
820821
addDescription(crApiVersion, schema, property);
821822
}
822823

823-
celValidationRules(property, schema);
824+
celValidationRules(crApiVersion, property, schema);
824825

825826
return schema;
826827
}
@@ -933,10 +934,11 @@ private void preserveUnknownStringFields(ObjectNode result) {
933934
/**
934935
* Adds CEL validation rules to the CRD for additional validation
935936
*
936-
* @param element The element where the CEL validation annotation will be checked
937-
* @param result The JSON Object where the CEL validation rules should be added
937+
* @param crApiVersion Strimzi API version for which the validation rules should be generated
938+
* @param element The element where the CEL validation annotation will be checked
939+
* @param result The JSON Object where the CEL validation rules should be added
938940
*/
939-
private void celValidationRules(Property element, ObjectNode result) {
941+
private void celValidationRules(ApiVersion crApiVersion, Property element, ObjectNode result) {
940942
// Annotation from the field has the priority. But if it does not exist, we try the type
941943
CelValidation celValidation = element.getAnnotation(CelValidation.class);
942944
if (celValidation == null) {
@@ -946,24 +948,35 @@ private void celValidationRules(Property element, ObjectNode result) {
946948
if (celValidation != null
947949
&& celValidation.rules() != null
948950
&& celValidation.rules().length > 0) {
949-
ArrayNode rules = result.putArray("x-kubernetes-validations");
951+
List<ObjectNode> ruleObjects = new ArrayList<>();
950952

951953
for (CelValidation.CelValidationRule rule : celValidation.rules()) {
952-
ObjectNode celRule = rules.addObject().put("rule", rule.rule());
954+
if (rule.versions().isEmpty() || ApiVersion.parseRange(rule.versions()).contains(crApiVersion)) {
955+
ObjectNode celRule = nf.objectNode();
956+
celRule.put("rule", rule.rule());
953957

954-
if (!rule.message().isEmpty()) {
955-
celRule.put("message", rule.message());
956-
}
957-
if (!rule.messageExpression().isEmpty()) {
958-
celRule.put("messageExpression", rule.messageExpression());
959-
}
960-
if (!rule.fieldPath().isEmpty()) {
961-
celRule.put("fieldPath", rule.fieldPath());
962-
}
963-
if (!rule.reason().isEmpty()) {
964-
celRule.put("reason", rule.reason());
958+
if (!rule.message().isEmpty()) {
959+
celRule.put("message", rule.message());
960+
}
961+
if (!rule.messageExpression().isEmpty()) {
962+
celRule.put("messageExpression", rule.messageExpression());
963+
}
964+
if (!rule.fieldPath().isEmpty()) {
965+
celRule.put("fieldPath", rule.fieldPath());
966+
}
967+
if (!rule.reason().isEmpty()) {
968+
celRule.put("reason", rule.reason());
969+
}
970+
971+
ruleObjects.add(celRule);
965972
}
966973
}
974+
975+
// There might be API versions where there is no rule. So we create the validations array only if there are any rules
976+
if (!ruleObjects.isEmpty()) {
977+
ArrayNode rules = result.putArray("x-kubernetes-validations");
978+
rules.addAll(ruleObjects);
979+
}
967980
}
968981
}
969982

crd-generator/src/main/java/io/strimzi/crdgenerator/annotations/CelValidation.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,5 +55,10 @@
5555
* @return Return fieldPath
5656
*/
5757
String fieldPath() default "";
58+
59+
/**
60+
* @return The versions in which this validation rule is used
61+
*/
62+
String versions() default "";
5863
}
5964
}

crd-generator/src/test/java/io/strimzi/crdgenerator/ExampleCrd.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ public class ExampleCrd<T, U extends Number, V extends U> extends CustomResource
148148
@JsonPropertyOrder({"foo", "bar"})
149149
@CelValidation(rules = {
150150
@CelValidation.CelValidationRule(rule = "size(self.foo) >= 5", message = "foo needs to be at least 5 characters long", fieldPath = ".foo", reason = "FieldValueInvalid"),
151-
@CelValidation.CelValidationRule(rule = "size(self.bar) >= 5", message = "bar needs to be at least 5 characters long", fieldPath = ".bar", reason = "FieldValueInvalid")
151+
@CelValidation.CelValidationRule(rule = "size(self.bar) >= 5", message = "bar needs to be at least 5 characters long", fieldPath = ".bar", reason = "FieldValueInvalid", versions = "v1beta1")
152152
})
153153
public static class ObjectProperty {
154154
private String foo;
@@ -285,6 +285,9 @@ public void setIntProperty(int intProperty) {
285285
@Description("An example long property")
286286
@Example("42")
287287
@Minimum(42)
288+
@CelValidation(rules = {
289+
@CelValidation.CelValidationRule(rule = "self >= 1874", message = "long property needs to be 1874 or higher", versions = "v1beta1")
290+
})
288291
public long getLongProperty() {
289292
return longProperty;
290293
}

crd-generator/src/test/resources/io/strimzi/crdgenerator/simpleTest.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,6 @@ spec:
8282
message: foo needs to be at least 5 characters long
8383
fieldPath: .foo
8484
reason: FieldValueInvalid
85-
- rule: size(self.bar) >= 5
86-
message: bar needs to be at least 5 characters long
87-
fieldPath: .bar
88-
reason: FieldValueInvalid
8985
mapStringObject:
9086
x-kubernetes-preserve-unknown-fields: true
9187
type: object
@@ -671,6 +667,9 @@ spec:
671667
example: 42
672668
minimum: 42
673669
description: An example long property.
670+
x-kubernetes-validations:
671+
- rule: self >= 1874
672+
message: long property needs to be 1874 or higher
674673
booleanProperty:
675674
type: boolean
676675
normalEnum:

crd-generator/src/test/resources/io/strimzi/crdgenerator/simpleTestHelmMetadata.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,10 +88,6 @@ spec:
8888
message: foo needs to be at least 5 characters long
8989
fieldPath: .foo
9090
reason: FieldValueInvalid
91-
- rule: size(self.bar) >= 5
92-
message: bar needs to be at least 5 characters long
93-
fieldPath: .bar
94-
reason: FieldValueInvalid
9591
mapStringObject:
9692
x-kubernetes-preserve-unknown-fields: true
9793
type: object
@@ -677,6 +673,9 @@ spec:
677673
example: 42
678674
minimum: 42
679675
description: An example long property.
676+
x-kubernetes-validations:
677+
- rule: self >= 1874
678+
message: long property needs to be 1874 or higher
680679
booleanProperty:
681680
type: boolean
682681
normalEnum:

crd-generator/src/test/resources/io/strimzi/crdgenerator/simpleTestWithoutDescriptions.yaml

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,10 +80,6 @@ spec:
8080
message: foo needs to be at least 5 characters long
8181
fieldPath: .foo
8282
reason: FieldValueInvalid
83-
- rule: size(self.bar) >= 5
84-
message: bar needs to be at least 5 characters long
85-
fieldPath: .bar
86-
reason: FieldValueInvalid
8783
mapStringObject:
8884
x-kubernetes-preserve-unknown-fields: true
8985
type: object
@@ -662,6 +658,9 @@ spec:
662658
type: integer
663659
example: 42
664660
minimum: 42
661+
x-kubernetes-validations:
662+
- rule: self >= 1874
663+
message: long property needs to be 1874 or higher
665664
booleanProperty:
666665
type: boolean
667666
normalEnum:

0 commit comments

Comments
 (0)