Skip to content

Commit

Permalink
fix: simple enums are now supported when generating CRDs
Browse files Browse the repository at this point in the history
`Types.applyTypeArguments` doesn't crash when encountering differing
cardinality between type definition and actual arguments, which was the
case when encountering an enum property. Such properties are now
generated by enumerating their cases name and recording them in the
validation schema. Not sure if that actually covers all cases.

Fixes #2819.
  • Loading branch information
metacosm authored and manusa committed Feb 24, 2021
1 parent ceea852 commit 3ec8f49
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 20 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#### Bugs
* Apiextensions DSL should use NonNamespaceOperation for CustomResourceDefinitions
* Fix #2819: simple enums are now supported when generating CRDs
* CNFE when initialzing CustomResource instances

#### Improvements
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
*/
package io.fabric8.crd.generator;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
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 @@ -183,7 +185,18 @@ public T internalFrom(TypeRef typeRef) {
if (typeRef instanceof ClassRef) { // Handle complex types
ClassRef classRef = (ClassRef) typeRef;
TypeDef def = classRef.getDefinition();
return internalFrom(def);

// check if we're dealing with an enum
if(def.isEnum()) {
final JsonNode[] enumValues = def.getProperties().stream()
.map(Property::getName)
.map(JsonNodeFactory.instance::textNode)
.toArray(JsonNode[]::new);
return enumProperty(enumValues);
} else {
return internalFrom(def);
}

}
return null;
}
Expand Down Expand Up @@ -214,4 +227,5 @@ public T internalFrom(TypeRef typeRef) {
*/
protected abstract T singleProperty(String typeName);

protected abstract T enumProperty(JsonNode... enumValues);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
import io.sundr.codegen.model.PropertyBuilder;
import io.sundr.codegen.model.TypeDef;
import io.sundr.codegen.model.TypeDefBuilder;
import io.sundr.codegen.model.TypeParamDef;
import io.sundr.codegen.model.TypeParamRef;
import io.sundr.codegen.model.TypeRef;
import java.util.HashMap;
Expand Down Expand Up @@ -88,26 +89,33 @@ public static Set<TypeDef> unrollHierarchy(TypeDef typeDef) {
*/
public static TypeDef applyTypeArguments(ClassRef ref) {
Map<String, TypeRef> bounds = new HashMap<>();
for (int i = 0; i < ref.getArguments().size(); i++) {
bounds.put(ref.getDefinition().getParameters().get(i).getName(), ref.getArguments().get(i));
}
final List<TypeRef> arguments = ref.getArguments();
final TypeDef definition = ref.getDefinition();
final List<TypeParamDef> parameters = definition.getParameters();
// only apply type arguments if their number matches the definition
if (arguments.size() == parameters.size()) {
for (int i = 0; i < arguments.size(); i++) {
bounds.put(parameters.get(i).getName(), arguments.get(i));
}

return new TypeDefBuilder(ref.getDefinition()).accept(new TypedVisitor<PropertyBuilder>() {
@Override
public void visit(PropertyBuilder property) {
TypeRef typeRef = property.buildTypeRef();
if (typeRef instanceof TypeParamRef) {
TypeParamRef typeParamRef = (TypeParamRef) typeRef;
String key = typeParamRef.getName();
if (bounds.containsKey(key)) {
TypeRef paramRef = bounds.get(key);
if (paramRef != null) {
property.withTypeRef(paramRef);
return new TypeDefBuilder(definition).accept(new TypedVisitor<PropertyBuilder>() {
@Override
public void visit(PropertyBuilder property) {
TypeRef typeRef = property.buildTypeRef();
if (typeRef instanceof TypeParamRef) {
TypeParamRef typeParamRef = (TypeParamRef) typeRef;
String key = typeParamRef.getName();
if (bounds.containsKey(key)) {
TypeRef paramRef = bounds.get(key);
if (paramRef != null) {
property.withTypeRef(paramRef);
}
}
}
}
}
}).build();
}).build();
}
return new TypeDefBuilder(definition).build();
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.fabric8.crd.generator.v1;

import com.fasterxml.jackson.databind.JsonNode;
import io.fabric8.crd.generator.AbstractJsonSchema;
import io.fabric8.kubernetes.api.model.apiextensions.v1.JSONSchemaProps;
import io.fabric8.kubernetes.api.model.apiextensions.v1.JSONSchemaPropsBuilder;
Expand Down Expand Up @@ -77,13 +78,16 @@ protected JSONSchemaProps collectionProperty(JSONSchemaProps schema) {

@Override
protected JSONSchemaProps singleProperty(String typeName) {
return new JSONSchemaPropsBuilder()
.withType(typeName)
.build();
return new JSONSchemaPropsBuilder().withType(typeName).build();
}

@Override
protected JSONSchemaProps mappedProperty(TypeRef ref) {
return JSON_SCHEMA_INT_OR_STRING;
}

@Override
protected JSONSchemaProps enumProperty(JsonNode... enumValues) {
return new JSONSchemaPropsBuilder().withType("string").withEnum(enumValues).build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
*/
package io.fabric8.crd.generator.v1beta1;

import com.fasterxml.jackson.databind.JsonNode;
import io.fabric8.crd.generator.AbstractJsonSchema;
import io.fabric8.kubernetes.api.model.apiextensions.v1beta1.JSONSchemaProps;
import io.fabric8.kubernetes.api.model.apiextensions.v1beta1.JSONSchemaPropsBuilder;
Expand Down Expand Up @@ -87,4 +88,9 @@ protected JSONSchemaProps singleProperty(String typeName) {
protected JSONSchemaProps mappedProperty(TypeRef ref) {
return JSON_SCHEMA_INT_OR_STRING;
}

@Override
protected JSONSchemaProps enumProperty(JsonNode... enumValues) {
return new JSONSchemaPropsBuilder().withType("string").withEnum(enumValues).build();
}
}

0 comments on commit 3ec8f49

Please sign in to comment.