diff --git a/crd-generator/api/src/test/java/io/fabric8/crd/example/extraction/DeeplyNestedSchemaSwaps.java b/crd-generator/api/src/test/java/io/fabric8/crd/example/extraction/DeeplyNestedSchemaSwaps.java new file mode 100644 index 00000000000..aa5136f77ef --- /dev/null +++ b/crd-generator/api/src/test/java/io/fabric8/crd/example/extraction/DeeplyNestedSchemaSwaps.java @@ -0,0 +1,49 @@ +/** + * Copyright (C) 2015 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package io.fabric8.crd.example.extraction; + +import io.fabric8.crd.generator.annotation.SchemaSwap; +import io.fabric8.kubernetes.client.CustomResource; + +@SchemaSwap(originalType = DeeplyNestedSchemaSwaps.MyObject.class, fieldName = "shouldBeString", targetType = String.class) +public class DeeplyNestedSchemaSwaps extends CustomResource { + + public static class Spec { + private MyObject myObject; + private Level1 level1; + } + + private static class Level1 { + private Level2 level2a; + private MyObject myObject; + private Level2 level2b; + } + + private static class Level2 { + private MyObject myObject1; + private Level3 level3; + private MyObject myObject2; + } + + private static class Level3 { + private MyObject myObject1; + private MyObject myObject2; + } + + public static class MyObject { + private int shouldBeString; + } +} diff --git a/crd-generator/api/src/test/java/io/fabric8/crd/generator/v1/JsonSchemaTest.java b/crd-generator/api/src/test/java/io/fabric8/crd/generator/v1/JsonSchemaTest.java index da32ce91ff5..c8574c7099a 100644 --- a/crd-generator/api/src/test/java/io/fabric8/crd/generator/v1/JsonSchemaTest.java +++ b/crd-generator/api/src/test/java/io/fabric8/crd/generator/v1/JsonSchemaTest.java @@ -18,6 +18,7 @@ import com.fasterxml.jackson.databind.JsonNode; import io.fabric8.crd.example.annotated.Annotated; import io.fabric8.crd.example.basic.Basic; +import io.fabric8.crd.example.extraction.DeeplyNestedSchemaSwaps; import io.fabric8.crd.example.extraction.Extraction; import io.fabric8.crd.example.extraction.IncorrectExtraction; import io.fabric8.crd.example.extraction.IncorrectExtraction2; @@ -29,6 +30,7 @@ import io.sundr.model.TypeDef; import org.junit.jupiter.api.Test; +import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @@ -42,8 +44,7 @@ void shouldCreateJsonSchemaFromClass() { TypeDef person = Types.typeDefFrom(Person.class); JSONSchemaProps schema = JsonSchema.from(person); assertNotNull(schema); - Map properties = schema.getProperties(); - assertEquals(7, properties.size()); + Map properties = assertSchemaHasNumberOfProperties(schema, 7); final List personTypes = properties.get("type").getEnum().stream().map(JsonNode::asText) .collect(Collectors.toList()); assertEquals(2, personTypes.size()); @@ -77,11 +78,9 @@ void shouldAugmentPropertiesSchemaFromAnnotations() { TypeDef annotated = Types.typeDefFrom(Annotated.class); JSONSchemaProps schema = JsonSchema.from(annotated); assertNotNull(schema); - Map properties = schema.getProperties(); - assertEquals(2, properties.size()); + Map properties = assertSchemaHasNumberOfProperties(schema, 2); final JSONSchemaProps specSchema = properties.get("spec"); - Map spec = specSchema.getProperties(); - assertEquals(6, spec.size()); + Map spec = assertSchemaHasNumberOfProperties(specSchema, 6); // check descriptions are present assertTrue(spec.containsKey("from-field")); @@ -120,11 +119,9 @@ void shouldProduceKubernetesPreserveFields() { TypeDef containingJson = Types.typeDefFrom(ContainingJson.class); JSONSchemaProps schema = JsonSchema.from(containingJson); assertNotNull(schema); - Map properties = schema.getProperties(); - assertEquals(2, properties.size()); + Map properties = assertSchemaHasNumberOfProperties(schema, 2); final JSONSchemaProps specSchema = properties.get("spec"); - Map spec = specSchema.getProperties(); - assertEquals(3, spec.size()); + Map spec = assertSchemaHasNumberOfProperties(specSchema, 3); // check preserve unknown fields is present assertTrue(spec.containsKey("free")); @@ -148,11 +145,9 @@ void shouldExtractPropertiesSchemaFromExtractValueAnnotation() { TypeDef extraction = Types.typeDefFrom(Extraction.class); JSONSchemaProps schema = JsonSchema.from(extraction); assertNotNull(schema); - Map properties = schema.getProperties(); - assertEquals(2, properties.size()); + Map properties = assertSchemaHasNumberOfProperties(schema, 2); final JSONSchemaProps specSchema = properties.get("spec"); - Map spec = specSchema.getProperties(); - assertEquals(2, spec.size()); + Map spec = assertSchemaHasNumberOfProperties(specSchema, 2); // check typed SchemaFrom JSONSchemaProps foo = spec.get("foo"); @@ -184,32 +179,47 @@ void shouldExtractPropertiesSchemaFromSchemaSwapAnnotations() { TypeDef extraction = Types.typeDefFrom(MultipleSchemaSwaps.class); JSONSchemaProps schema = JsonSchema.from(extraction); assertNotNull(schema); - Map properties = schema.getProperties(); - assertEquals(2, properties.size()); + Map properties = assertSchemaHasNumberOfProperties(schema, 2); final JSONSchemaProps specSchema = properties.get("spec"); - Map spec = specSchema.getProperties(); - assertEquals(3, spec.size()); + Map spec = assertSchemaHasNumberOfProperties(specSchema, 3); // 'first' is replaced by SchemaSwap from int to string JSONSchemaProps first = spec.get("first"); - Map firstProps = first.getProperties(); - assertNotNull(firstProps); - JSONSchemaProps firstProperty = firstProps.get("shouldBeString"); - assertEquals("string", firstProperty.getType()); + assertPropertyHasType(first, "shouldBeString", "string"); // 'second' is replaced by the same SchemaSwap that is applied multiple times JSONSchemaProps second = spec.get("second"); - Map secondProps = second.getProperties(); - assertNotNull(secondProps); - JSONSchemaProps secondProperty = secondProps.get("shouldBeString"); - assertEquals("string", secondProperty.getType()); + assertPropertyHasType(second, "shouldBeString", "string"); // 'third' is replaced by the another SchemaSwap JSONSchemaProps third = spec.get("third"); - Map thirdProps = third.getProperties(); - assertNotNull(thirdProps); - JSONSchemaProps thirdProperty = thirdProps.get("shouldBeInt"); - assertEquals("integer", thirdProperty.getType()); + assertPropertyHasType(third, "shouldBeInt", "integer"); + } + + @Test + void shouldApplySchemaSwapsMultipleTimesInDeepClassHierarchy() { + TypeDef extraction = Types.typeDefFrom(DeeplyNestedSchemaSwaps.class); + JSONSchemaProps schema = JsonSchema.from(extraction); + assertNotNull(schema); + Map properties = assertSchemaHasNumberOfProperties(schema, 2); + Map spec = assertSchemaHasNumberOfProperties(properties.get("spec"), 2); + + assertPropertyHasType(spec.get("myObject"), "shouldBeString", "string"); + Map level1 = assertSchemaHasNumberOfProperties(spec.get("level1"), 3); + + assertPropertyHasType(level1.get("myObject"), "shouldBeString", "string"); + List> levels2 = new ArrayList<>(); + levels2.add(assertSchemaHasNumberOfProperties(level1.get("level2a"), 3)); + levels2.add(assertSchemaHasNumberOfProperties(level1.get("level2b"), 3)); + + for (Map level2 : levels2) { + assertPropertyHasType(level2.get("myObject1"), "shouldBeString", "string"); + assertPropertyHasType(level2.get("myObject2"), "shouldBeString", "string"); + + Map level3 = assertSchemaHasNumberOfProperties(level2.get("level3"), 2); + assertPropertyHasType(level3.get("myObject1"), "shouldBeString", "string"); + assertPropertyHasType(level3.get("myObject2"), "shouldBeString", "string"); + } } @Test @@ -233,4 +243,18 @@ void shouldThrowIfSchemaSwapHasUnmatchedClass() { + ".example.extraction.FooExtractor) on io.fabric8.crd.example.extraction.IncorrectExtraction2", exception.getMessage()); } + + private static Map assertSchemaHasNumberOfProperties(JSONSchemaProps specSchema, int expected) { + Map spec = specSchema.getProperties(); + assertEquals(expected, spec.size()); + return spec; + } + + private static void assertPropertyHasType(JSONSchemaProps spec, String name, String expectedType) { + Map properties = spec.getProperties(); + assertNotNull(properties); + JSONSchemaProps property = properties.get(name); + assertNotNull(property, "Property " + name + " should exist"); + assertEquals(expectedType, property.getType(), "Property " + name + " should have expected type"); + } }