diff --git a/core/pom.xml b/core/pom.xml
index 689c3ef6..b8c3950b 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -50,7 +50,6 @@
-
io.fabric8
kubernetes-client
diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionController.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionController.java
index 077507ab..7b6f9e6f 100644
--- a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionController.java
+++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/AsyncConversionController.java
@@ -28,6 +28,8 @@ public void registerMapper(AsyncMapper, ?> mapper) {
throw new IllegalStateException(MAPPER_ALREADY_REGISTERED_FOR_VERSION_MESSAGE + version);
}
mappers.put(version, mapper);
+ Utils.registerCustomKind(
+ Utils.getFirstTypeArgumentFromInterface(mapper.getClass(), AsyncMapper.class));
}
@Override
diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionController.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionController.java
index 4c98f83c..00ba1f36 100644
--- a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionController.java
+++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/ConversionController.java
@@ -27,6 +27,8 @@ public void registerMapper(Mapper, ?> mapper) {
throw new IllegalStateException(MAPPER_ALREADY_REGISTERED_FOR_VERSION_MESSAGE + version);
}
mappers.put(version, mapper);
+ Utils.registerCustomKind(
+ Utils.getFirstTypeArgumentFromInterface(mapper.getClass(), Mapper.class));
}
@Override
diff --git a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Utils.java b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Utils.java
index 7f16d81e..a423ddea 100644
--- a/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Utils.java
+++ b/core/src/main/java/io/javaoperatorsdk/webhook/conversion/Utils.java
@@ -1,5 +1,11 @@
package io.javaoperatorsdk.webhook.conversion;
+import java.lang.reflect.ParameterizedType;
+import java.util.Arrays;
+
+import io.fabric8.kubernetes.api.model.HasMetadata;
+import io.fabric8.kubernetes.internal.KubernetesDeserializer;
+
public class Utils {
private Utils() {}
@@ -12,4 +18,25 @@ public static String versionOfApiVersion(String apiVersion) {
var lastDelimiter = apiVersion.lastIndexOf("/");
return apiVersion.substring(lastDelimiter + 1);
}
+
+ public static void registerCustomKind(Class extends HasMetadata> clazz) {
+ KubernetesDeserializer.registerCustomKind(HasMetadata.getApiVersion(clazz),
+ HasMetadata.getKind(clazz), clazz);
+ }
+
+ @SuppressWarnings("unchecked")
+ public static Class extends HasMetadata> getFirstTypeArgumentFromInterface(Class> clazz,
+ Class> expectedImplementedInterface) {
+ return (Class extends HasMetadata>) Arrays.stream(clazz.getGenericInterfaces())
+ .filter(type -> type.getTypeName().startsWith(expectedImplementedInterface.getName())
+ && type instanceof ParameterizedType)
+ .map(ParameterizedType.class::cast)
+ .findFirst()
+ .map(t -> (Class>) t.getActualTypeArguments()[0])
+ .orElseThrow(() -> new RuntimeException(
+ "Couldn't retrieve generic parameter type from " + clazz.getSimpleName()
+ + " because it doesn't implement "
+ + expectedImplementedInterface.getSimpleName()
+ + " directly"));
+ }
}
diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/UtilsTest.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/UtilsTest.java
index 6229d126..bed5264a 100644
--- a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/UtilsTest.java
+++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/UtilsTest.java
@@ -2,6 +2,13 @@
import org.junit.jupiter.api.Test;
+import io.javaoperatorsdk.webhook.conversion.crd.CustomResourceV1;
+import io.javaoperatorsdk.webhook.conversion.crd.CustomResourceV2;
+import io.javaoperatorsdk.webhook.conversion.mapper.AsyncV1Mapper;
+import io.javaoperatorsdk.webhook.conversion.mapper.AsyncV2Mapper;
+import io.javaoperatorsdk.webhook.conversion.mapper.CustomResourceV1Mapper;
+import io.javaoperatorsdk.webhook.conversion.mapper.CustomResourceV2Mapper;
+
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.*;
@@ -13,4 +20,16 @@ void getsVersionFromApiVersion() {
assertThat(Utils.versionOfApiVersion("extensions/v1beta1")).isEqualTo("v1beta1");
}
+ @Test
+ void getMapperResourceType() {
+ assertThat(Utils.getFirstTypeArgumentFromInterface(CustomResourceV1Mapper.class, Mapper.class))
+ .isEqualTo(CustomResourceV1.class);
+ assertThat(Utils.getFirstTypeArgumentFromInterface(CustomResourceV2Mapper.class, Mapper.class))
+ .isEqualTo(CustomResourceV2.class);
+ assertThat(Utils.getFirstTypeArgumentFromInterface(AsyncV1Mapper.class, AsyncMapper.class))
+ .isEqualTo(CustomResourceV1.class);
+ assertThat(Utils.getFirstTypeArgumentFromInterface(AsyncV2Mapper.class, AsyncMapper.class))
+ .isEqualTo(CustomResourceV2.class);
+ }
+
}
diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1.java
index ea003ef6..7c277104 100644
--- a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1.java
+++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV1.java
@@ -9,7 +9,7 @@
@Group("sample.javaoperatorsdk")
@Version("v1")
-@Kind("MultiVersionCustomResource")
+@Kind("MultiVersionTestCustomResource")
@ShortNames("mv1")
public class CustomResourceV1
extends
diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2.java
index 0f357f92..75f25ead 100644
--- a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2.java
+++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV2.java
@@ -9,7 +9,7 @@
@Group("sample.javaoperatorsdk")
@Version(value = "v2", storage = false)
-@Kind("MultiVersionCustomResource")
+@Kind("MultiVersionTestCustomResource")
@ShortNames("mv2")
public class CustomResourceV2
extends
diff --git a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3.java b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3.java
index 2916fb8f..76d7be68 100644
--- a/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3.java
+++ b/core/src/test/java/io/javaoperatorsdk/webhook/conversion/crd/CustomResourceV3.java
@@ -9,7 +9,7 @@
@Group("sample.javaoperatorsdk")
@Version(value = "v3", storage = false)
-@Kind("MultiVersionCustomResource")
+@Kind("MultiVersionTestCustomResource")
@ShortNames("mv3")
public class CustomResourceV3
extends
diff --git a/pom.xml b/pom.xml
index d9eba037..d0f394d4 100644
--- a/pom.xml
+++ b/pom.xml
@@ -158,9 +158,6 @@
org.apache.maven.plugins
maven-surefire-plugin
${maven-surefire-plugin.version}
-
- 3
-
org.apache.maven.plugins
diff --git a/samples/commons/pom.xml b/samples/commons/pom.xml
new file mode 100644
index 00000000..3d70ff7b
--- /dev/null
+++ b/samples/commons/pom.xml
@@ -0,0 +1,46 @@
+
+
+ 4.0.0
+
+ io.javaoperatorsdk
+ admission-controller-framework-samples
+ 0.2.1-SNAPSHOT
+
+
+ io.javaoperatorsdk.admissioncontroller.sample
+ sample-commons
+ Admission Controller Framework - Samples - Commons
+
+
+ 11
+ 2.6.6
+
+
+
+
+ io.fabric8
+ kubernetes-client
+
+
+ io.javaoperatorsdk
+ admission-controller-framework-core
+ ${project.version}
+
+
+ io.fabric8
+ crd-generator-apt
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-maven-plugin
+ ${spring-boot-dependencies.version}
+
+
+
+
+
diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResource.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResource.java
new file mode 100644
index 00000000..cd6bea05
--- /dev/null
+++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResource.java
@@ -0,0 +1,16 @@
+package io.javaoperatorsdk.webhook.sample.commons.customresource;
+
+import io.fabric8.kubernetes.client.CustomResource;
+import io.fabric8.kubernetes.model.annotation.Group;
+import io.fabric8.kubernetes.model.annotation.Kind;
+import io.fabric8.kubernetes.model.annotation.ShortNames;
+import io.fabric8.kubernetes.model.annotation.Version;
+
+@Group("sample.javaoperatorsdk")
+@Version(value = "v1", storage = false)
+@Kind("MultiVersionCustomResource")
+@ShortNames("tcr")
+public class MultiVersionCustomResource
+ extends CustomResource {
+
+}
diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceSpec.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceSpec.java
new file mode 100644
index 00000000..8a43e055
--- /dev/null
+++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceSpec.java
@@ -0,0 +1,15 @@
+package io.javaoperatorsdk.webhook.sample.commons.customresource;
+
+public class MultiVersionCustomResourceSpec {
+
+ private int value;
+
+ public int getValue() {
+ return value;
+ }
+
+ public MultiVersionCustomResourceSpec setValue(int value) {
+ this.value = value;
+ return this;
+ }
+}
diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceSpecV2.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceSpecV2.java
new file mode 100644
index 00000000..13ac0848
--- /dev/null
+++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceSpecV2.java
@@ -0,0 +1,25 @@
+package io.javaoperatorsdk.webhook.sample.commons.customresource;
+
+public class MultiVersionCustomResourceSpecV2 {
+
+ private String value;
+
+ private String additionalValue;
+
+ public String getValue() {
+ return value;
+ }
+
+ public MultiVersionCustomResourceSpecV2 setValue(String value) {
+ this.value = value;
+ return this;
+ }
+
+ public String getAdditionalValue() {
+ return additionalValue;
+ }
+
+ public void setAdditionalValue(String additionalValue) {
+ this.additionalValue = additionalValue;
+ }
+}
diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceStatus.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceStatus.java
new file mode 100644
index 00000000..3735d14b
--- /dev/null
+++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceStatus.java
@@ -0,0 +1,16 @@
+package io.javaoperatorsdk.webhook.sample.commons.customresource;
+
+public class MultiVersionCustomResourceStatus {
+
+ private Boolean ready;
+
+ public Boolean getReady() {
+ return ready;
+ }
+
+ public MultiVersionCustomResourceStatus setReady(Boolean ready) {
+ this.ready = ready;
+ return this;
+ }
+}
+
diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceStatusV2.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceStatusV2.java
new file mode 100644
index 00000000..528882ce
--- /dev/null
+++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceStatusV2.java
@@ -0,0 +1,27 @@
+package io.javaoperatorsdk.webhook.sample.commons.customresource;
+
+
+public class MultiVersionCustomResourceStatusV2 {
+
+ private Boolean ready;
+
+ private String message;
+
+ public Boolean getReady() {
+ return ready;
+ }
+
+ public MultiVersionCustomResourceStatusV2 setReady(Boolean ready) {
+ this.ready = ready;
+ return this;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ public MultiVersionCustomResourceStatusV2 setMessage(String message) {
+ this.message = message;
+ return this;
+ }
+}
diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceV2.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceV2.java
new file mode 100644
index 00000000..1ae12dae
--- /dev/null
+++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/customresource/MultiVersionCustomResourceV2.java
@@ -0,0 +1,15 @@
+package io.javaoperatorsdk.webhook.sample.commons.customresource;
+
+import io.fabric8.kubernetes.client.CustomResource;
+import io.fabric8.kubernetes.model.annotation.Group;
+import io.fabric8.kubernetes.model.annotation.Kind;
+import io.fabric8.kubernetes.model.annotation.ShortNames;
+import io.fabric8.kubernetes.model.annotation.Version;
+
+@Group("sample.javaoperatorsdk")
+@Version(value = "v2")
+@Kind("MultiVersionCustomResource")
+@ShortNames("tcr")
+public class MultiVersionCustomResourceV2
+ extends CustomResource {
+}
diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/mapper/AsyncV1Mapper.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/mapper/AsyncV1Mapper.java
new file mode 100644
index 00000000..9e37f727
--- /dev/null
+++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/mapper/AsyncV1Mapper.java
@@ -0,0 +1,27 @@
+package io.javaoperatorsdk.webhook.sample.commons.mapper;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+
+import io.javaoperatorsdk.webhook.conversion.AsyncMapper;
+import io.javaoperatorsdk.webhook.conversion.TargetVersion;
+import io.javaoperatorsdk.webhook.sample.commons.customresource.MultiVersionCustomResource;
+import io.javaoperatorsdk.webhook.sample.commons.customresource.MultiVersionCustomResourceV2;
+
+@TargetVersion("v1")
+public class AsyncV1Mapper
+ implements AsyncMapper {
+
+ private V1Mapper mapper = new V1Mapper();
+
+ @Override
+ public CompletionStage toHub(MultiVersionCustomResource resource) {
+ return CompletableFuture.completedStage(mapper.toHub(resource));
+ }
+
+ @Override
+ public CompletionStage fromHub(
+ MultiVersionCustomResourceV2 testCustomResourceV2) {
+ return CompletableFuture.completedStage(mapper.fromHub(testCustomResourceV2));
+ }
+}
diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/mapper/AsyncV2Mapper.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/mapper/AsyncV2Mapper.java
new file mode 100644
index 00000000..b941ff23
--- /dev/null
+++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/mapper/AsyncV2Mapper.java
@@ -0,0 +1,27 @@
+package io.javaoperatorsdk.webhook.sample.commons.mapper;
+
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionStage;
+
+import io.javaoperatorsdk.webhook.conversion.AsyncMapper;
+import io.javaoperatorsdk.webhook.conversion.TargetVersion;
+import io.javaoperatorsdk.webhook.sample.commons.customresource.MultiVersionCustomResourceV2;
+
+@TargetVersion("v2")
+public class AsyncV2Mapper
+ implements AsyncMapper {
+
+ private V2Mapper mapper = new V2Mapper();
+
+ @Override
+ public CompletionStage toHub(
+ MultiVersionCustomResourceV2 resource) {
+ return CompletableFuture.completedStage(mapper.toHub(resource));
+ }
+
+ @Override
+ public CompletionStage fromHub(
+ MultiVersionCustomResourceV2 multiVersionCustomResourceV2) {
+ return CompletableFuture.completedStage(mapper.fromHub(multiVersionCustomResourceV2));
+ }
+}
diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/mapper/V1Mapper.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/mapper/V1Mapper.java
new file mode 100644
index 00000000..7d5d305f
--- /dev/null
+++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/mapper/V1Mapper.java
@@ -0,0 +1,48 @@
+package io.javaoperatorsdk.webhook.sample.commons.mapper;
+
+import io.javaoperatorsdk.webhook.conversion.Mapper;
+import io.javaoperatorsdk.webhook.conversion.TargetVersion;
+import io.javaoperatorsdk.webhook.sample.commons.customresource.*;
+
+@TargetVersion("v1")
+public class V1Mapper implements Mapper {
+
+
+ public static final String DEFAULT_ADDITIONAL_VALUE = "default_additional_value";
+
+ @Override
+ public MultiVersionCustomResourceV2 toHub(MultiVersionCustomResource resource) {
+ var hub = new MultiVersionCustomResourceV2();
+ hub.setMetadata(resource.getMetadata());
+
+ var spec = new MultiVersionCustomResourceSpecV2();
+ spec.setValue(String.valueOf(resource.getSpec().getValue()));
+ spec.setAdditionalValue(DEFAULT_ADDITIONAL_VALUE);
+ hub.setSpec(spec);
+
+
+ if (resource.getStatus() != null) {
+ var status = new MultiVersionCustomResourceStatusV2();
+ status.setReady(resource.getStatus().getReady());
+ hub.setStatus(status);
+ }
+ return hub;
+ }
+
+ @Override
+ public MultiVersionCustomResource fromHub(MultiVersionCustomResourceV2 hub) {
+ var res = new MultiVersionCustomResource();
+ res.setMetadata(hub.getMetadata());
+
+ var spec = new MultiVersionCustomResourceSpec();
+ spec.setValue(Integer.parseInt(hub.getSpec().getValue()));
+ res.setSpec(spec);
+
+ if (hub.getStatus() != null) {
+ var status = new MultiVersionCustomResourceStatus();
+ status.setReady(hub.getStatus().getReady());
+ res.setStatus(status);
+ }
+ return res;
+ }
+}
diff --git a/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/mapper/V2Mapper.java b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/mapper/V2Mapper.java
new file mode 100644
index 00000000..9342160d
--- /dev/null
+++ b/samples/commons/src/main/java/io/javaoperatorsdk/webhook/sample/commons/mapper/V2Mapper.java
@@ -0,0 +1,21 @@
+package io.javaoperatorsdk.webhook.sample.commons.mapper;
+
+import io.javaoperatorsdk.webhook.conversion.Mapper;
+import io.javaoperatorsdk.webhook.conversion.TargetVersion;
+import io.javaoperatorsdk.webhook.sample.commons.customresource.MultiVersionCustomResourceV2;
+
+@TargetVersion("v2")
+public class V2Mapper
+ implements Mapper {
+
+ @Override
+ public MultiVersionCustomResourceV2 toHub(MultiVersionCustomResourceV2 resource) {
+ return resource;
+ }
+
+ @Override
+ public MultiVersionCustomResourceV2 fromHub(
+ MultiVersionCustomResourceV2 multiVersionCustomResourceV2) {
+ return multiVersionCustomResourceV2;
+ }
+}
diff --git a/samples/pom.xml b/samples/pom.xml
index 352a8d9f..d3ce7434 100644
--- a/samples/pom.xml
+++ b/samples/pom.xml
@@ -11,6 +11,7 @@
pom
Admission Controller Framework - Samples
+ commons
spring-boot
quarkus
diff --git a/samples/quarkus/pom.xml b/samples/quarkus/pom.xml
index a6952857..f7464803 100644
--- a/samples/quarkus/pom.xml
+++ b/samples/quarkus/pom.xml
@@ -59,6 +59,11 @@
org.jboss.resteasy
resteasy-jackson2-provider
+
+ io.javaoperatorsdk.admissioncontroller.sample
+ sample-commons
+ ${project.version}
+
diff --git a/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionControllerConfig.java b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerConfig.java
similarity index 98%
rename from samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionControllerConfig.java
rename to samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerConfig.java
index 344149c3..b60990fe 100644
--- a/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionControllerConfig.java
+++ b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionControllerConfig.java
@@ -1,4 +1,4 @@
-package io.javaoperatorsdk.webhook.admission.sample.quarkus;
+package io.javaoperatorsdk.webhook.admission.sample.quarkus.admission;
import java.util.HashMap;
import java.util.concurrent.CompletableFuture;
diff --git a/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionEndpoint.java b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpoint.java
similarity index 98%
rename from samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionEndpoint.java
rename to samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpoint.java
index d544cb00..501a51a4 100644
--- a/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionEndpoint.java
+++ b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpoint.java
@@ -1,4 +1,4 @@
-package io.javaoperatorsdk.webhook.admission.sample.quarkus;
+package io.javaoperatorsdk.webhook.admission.sample.quarkus.admission;
import javax.inject.Inject;
import javax.inject.Named;
diff --git a/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/conversion/ConversionControllerConfig.java b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/conversion/ConversionControllerConfig.java
new file mode 100644
index 00000000..19a3ab9b
--- /dev/null
+++ b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/conversion/ConversionControllerConfig.java
@@ -0,0 +1,33 @@
+package io.javaoperatorsdk.webhook.admission.sample.quarkus.conversion;
+
+import javax.enterprise.context.Dependent;
+import javax.inject.Singleton;
+
+import io.javaoperatorsdk.webhook.conversion.AsyncConversionController;
+import io.javaoperatorsdk.webhook.conversion.ConversionController;
+import io.javaoperatorsdk.webhook.sample.commons.mapper.AsyncV1Mapper;
+import io.javaoperatorsdk.webhook.sample.commons.mapper.AsyncV2Mapper;
+import io.javaoperatorsdk.webhook.sample.commons.mapper.V1Mapper;
+import io.javaoperatorsdk.webhook.sample.commons.mapper.V2Mapper;
+
+@Dependent
+public class ConversionControllerConfig {
+
+
+ @Singleton
+ public ConversionController conversionController() {
+ var controller = new ConversionController();
+ controller.registerMapper(new V1Mapper());
+ controller.registerMapper(new V2Mapper());
+ return controller;
+ }
+
+ @Singleton
+ public AsyncConversionController asyncConversionController() {
+ var controller = new AsyncConversionController();
+ controller.registerMapper(new AsyncV1Mapper());
+ controller.registerMapper(new AsyncV2Mapper());
+ return controller;
+ }
+
+}
diff --git a/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/conversion/ConversionEndpoint.java b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/conversion/ConversionEndpoint.java
new file mode 100644
index 00000000..cd54662d
--- /dev/null
+++ b/samples/quarkus/src/main/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/conversion/ConversionEndpoint.java
@@ -0,0 +1,47 @@
+package io.javaoperatorsdk.webhook.admission.sample.quarkus.conversion;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionReview;
+import io.javaoperatorsdk.webhook.conversion.AsyncConversionController;
+import io.javaoperatorsdk.webhook.conversion.ConversionController;
+import io.smallrye.mutiny.Uni;
+
+@Path("/")
+public class ConversionEndpoint {
+
+ public static final String CONVERSION_PATH = "convert";
+ public static final String ASYNC_CONVERSION_PATH = "async-convert";
+
+ private final ConversionController conversionController;
+ private final AsyncConversionController asyncConversionController;
+
+ public ConversionEndpoint(ConversionController conversionController,
+ AsyncConversionController asyncConversionController) {
+ this.conversionController = conversionController;
+ this.asyncConversionController = asyncConversionController;
+ }
+
+
+ @POST
+ @Path(CONVERSION_PATH)
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public ConversionReview convert(ConversionReview conversionReview) {
+ return conversionController.handle(conversionReview);
+ }
+
+ @POST
+ @Path(ASYNC_CONVERSION_PATH)
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public Uni convertAsync(ConversionReview conversionReview) {
+ return Uni.createFrom()
+ .completionStage(() -> asyncConversionController.handle(conversionReview));
+ }
+
+}
diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionEndpointTest.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpointTest.java
similarity index 97%
rename from samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionEndpointTest.java
rename to samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpointTest.java
index 9d32bd13..97af8bc0 100644
--- a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/AdmissionEndpointTest.java
+++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/AdmissionEndpointTest.java
@@ -1,4 +1,4 @@
-package io.javaoperatorsdk.webhook.admission.sample.quarkus;
+package io.javaoperatorsdk.webhook.admission.sample.quarkus.admission;
import java.io.IOException;
import java.io.InputStream;
diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/NativeAdmissionEndpointIT.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/NativeAdmissionEndpointIT.java
similarity index 72%
rename from samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/NativeAdmissionEndpointIT.java
rename to samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/NativeAdmissionEndpointIT.java
index 80970f09..f42d13e2 100644
--- a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/NativeAdmissionEndpointIT.java
+++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/admission/NativeAdmissionEndpointIT.java
@@ -1,4 +1,4 @@
-package io.javaoperatorsdk.webhook.admission.sample.quarkus;
+package io.javaoperatorsdk.webhook.admission.sample.quarkus.admission;
import io.quarkus.test.junit.NativeImageTest;
diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/conversion/ConversionEndpointTest.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/conversion/ConversionEndpointTest.java
new file mode 100644
index 00000000..878b49b1
--- /dev/null
+++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/conversion/ConversionEndpointTest.java
@@ -0,0 +1,52 @@
+package io.javaoperatorsdk.webhook.admission.sample.quarkus.conversion;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.http.ContentType;
+
+import static io.javaoperatorsdk.webhook.admission.sample.quarkus.conversion.ConversionEndpoint.ASYNC_CONVERSION_PATH;
+import static io.javaoperatorsdk.webhook.admission.sample.quarkus.conversion.ConversionEndpoint.CONVERSION_PATH;
+import static io.restassured.RestAssured.given;
+import static org.hamcrest.CoreMatchers.is;
+
+@QuarkusTest
+class ConversionEndpointTest {
+
+ final static String expectedResult =
+ "{\"apiVersion\":\"apiextensions.k8s.io/v1\",\"kind\":\"ConversionReview\",\"response\":{\"convertedObjects\":[{\"apiVersion\":\"sample.javaoperatorsdk/v2\",\"kind\":\"MultiVersionCustomResource\",\"metadata\":{\"creationTimestamp\":\"2021-09-04T14:03:02Z\",\"name\":\"resource1\",\"namespace\":\"default\",\"resourceVersion\":\"143\",\"uid\":\"3415a7fc-162b-4300-b5da-fd6083580d66\"},\"spec\":{\"value\":\"1\",\"additionalValue\":\"default_additional_value\"},\"status\":{\"ready\":true,\"message\":null}},{\"apiVersion\":\"sample.javaoperatorsdk/v2\",\"kind\":\"MultiVersionCustomResource\",\"metadata\":{\"creationTimestamp\":\"2021-09-04T14:03:02Z\",\"name\":\"resource2\",\"namespace\":\"default\",\"resourceVersion\":\"14344\",\"uid\":\"1115a7fc-162b-4300-b5da-fd6083580d55\"},\"spec\":{\"value\":\"2\",\"additionalValue\":\"default_additional_value\"},\"status\":{\"ready\":false,\"message\":null}}],\"result\":{\"apiVersion\":\"v1\",\"kind\":\"Status\",\"status\":\"Success\"},\"uid\":\"705ab4f5-6393-11e8-b7cc-42010a800002\"}}";
+
+ @Disabled
+ @Test
+ void conversion() {
+ testConversion(CONVERSION_PATH);
+ }
+
+ @Disabled
+ @Test
+ void asyncConversion() {
+ testConversion(ASYNC_CONVERSION_PATH);
+ }
+
+ public void testConversion(String path) {
+ given().contentType(ContentType.JSON)
+ .body(jsonRequest())
+ .when().post("/" + path)
+ .then()
+ .statusCode(200)
+ .body(is(expectedResult));
+ }
+
+ private String jsonRequest() {
+ try (InputStream is = this.getClass().getResourceAsStream("/conversion-request.json")) {
+ return new String(is.readAllBytes(), StandardCharsets.UTF_8);
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+}
diff --git a/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/conversion/NativeConversionEndpointTest.java b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/conversion/NativeConversionEndpointTest.java
new file mode 100644
index 00000000..bb07997e
--- /dev/null
+++ b/samples/quarkus/src/test/java/io/javaoperatorsdk/webhook/admission/sample/quarkus/conversion/NativeConversionEndpointTest.java
@@ -0,0 +1,7 @@
+package io.javaoperatorsdk.webhook.admission.sample.quarkus.conversion;
+
+import io.quarkus.test.junit.NativeImageTest;
+
+@NativeImageTest
+public class NativeConversionEndpointTest extends ConversionEndpointTest {
+}
diff --git a/samples/quarkus/src/test/resources/conversion-request.json b/samples/quarkus/src/test/resources/conversion-request.json
new file mode 100644
index 00000000..bb07e07f
--- /dev/null
+++ b/samples/quarkus/src/test/resources/conversion-request.json
@@ -0,0 +1,47 @@
+{
+ "apiVersion": "apiextensions.k8s.io/v1",
+ "kind": "ConversionReview",
+ "request": {
+
+ "uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
+
+ "desiredAPIVersion": "sample.javaoperatorsdk/v2",
+
+ "objects": [
+ {
+ "kind": "MultiVersionCustomResource",
+ "apiVersion": "sample.javaoperatorsdk/v1",
+ "metadata": {
+ "creationTimestamp": "2021-09-04T14:03:02Z",
+ "name": "resource1",
+ "namespace": "default",
+ "resourceVersion": "143",
+ "uid": "3415a7fc-162b-4300-b5da-fd6083580d66"
+ },
+ "spec": {
+ "value": 1
+ },
+ "status":{
+ "ready": true
+ }
+ },
+ {
+ "kind": "MultiVersionCustomResource",
+ "apiVersion": "sample.javaoperatorsdk/v1",
+ "metadata": {
+ "creationTimestamp": "2021-09-04T14:03:02Z",
+ "name": "resource2",
+ "namespace": "default",
+ "resourceVersion": "14344",
+ "uid": "1115a7fc-162b-4300-b5da-fd6083580d55"
+ },
+ "spec": {
+ "value": 2
+ },
+ "status":{
+ "ready": false
+ }
+ }
+ ]
+}
+}
\ No newline at end of file
diff --git a/samples/spring-boot/pom.xml b/samples/spring-boot/pom.xml
index ea65aefe..3bec0ace 100644
--- a/samples/spring-boot/pom.xml
+++ b/samples/spring-boot/pom.xml
@@ -70,6 +70,16 @@
admission-controller-framework-core
${project.version}
+
+ io.javaoperatorsdk.admissioncontroller.sample
+ sample-commons
+ ${project.version}
+
+
+ org.assertj
+ assertj-core
+ test
+
diff --git a/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/Config.java b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionConfig.java
similarity index 97%
rename from samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/Config.java
rename to samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionConfig.java
index 1e83946a..fe024e23 100644
--- a/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/Config.java
+++ b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionConfig.java
@@ -1,4 +1,4 @@
-package io.javaoperatorsdk.webhook.sample.springboot;
+package io.javaoperatorsdk.webhook.sample.springboot.admission;
import java.util.HashMap;
import java.util.concurrent.CompletableFuture;
@@ -15,7 +15,7 @@
import io.javaoperatorsdk.webhook.admission.validation.Validator;
@Configuration
-public class Config {
+public class AdmissionConfig {
public static final String APP_NAME_LABEL_KEY = "app.kubernetes.io/name";
public static final String ERROR_MESSAGE = "Some error happened";
diff --git a/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/AdmissionEndpoint.java b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpoint.java
similarity index 98%
rename from samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/AdmissionEndpoint.java
rename to samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpoint.java
index a3c7d24d..585b8bc3 100644
--- a/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/AdmissionEndpoint.java
+++ b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpoint.java
@@ -1,4 +1,4 @@
-package io.javaoperatorsdk.webhook.sample.springboot;
+package io.javaoperatorsdk.webhook.sample.springboot.admission;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -14,7 +14,7 @@
import reactor.core.publisher.Mono;
-@RestController("/")
+@RestController
public class AdmissionEndpoint {
public static final String MUTATE_PATH = "mutate";
diff --git a/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/conversion/ConversionConfig.java b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/conversion/ConversionConfig.java
new file mode 100644
index 00000000..406899b0
--- /dev/null
+++ b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/conversion/ConversionConfig.java
@@ -0,0 +1,32 @@
+package io.javaoperatorsdk.webhook.sample.springboot.conversion;
+
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import io.javaoperatorsdk.webhook.conversion.AsyncConversionController;
+import io.javaoperatorsdk.webhook.conversion.ConversionController;
+import io.javaoperatorsdk.webhook.sample.commons.mapper.AsyncV1Mapper;
+import io.javaoperatorsdk.webhook.sample.commons.mapper.AsyncV2Mapper;
+import io.javaoperatorsdk.webhook.sample.commons.mapper.V1Mapper;
+import io.javaoperatorsdk.webhook.sample.commons.mapper.V2Mapper;
+
+@Configuration
+public class ConversionConfig {
+
+ @Bean
+ public ConversionController conversionController() {
+ var controller = new ConversionController();
+ controller.registerMapper(new V1Mapper());
+ controller.registerMapper(new V2Mapper());
+ return controller;
+ }
+
+ @Bean
+ public AsyncConversionController asyncConversionController() {
+ var controller = new AsyncConversionController();
+ controller.registerMapper(new AsyncV1Mapper());
+ controller.registerMapper(new AsyncV2Mapper());
+ return controller;
+ }
+
+}
diff --git a/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/conversion/ConversionEndpoint.java b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/conversion/ConversionEndpoint.java
new file mode 100644
index 00000000..0cecae93
--- /dev/null
+++ b/samples/spring-boot/src/main/java/io/javaoperatorsdk/webhook/sample/springboot/conversion/ConversionEndpoint.java
@@ -0,0 +1,41 @@
+package io.javaoperatorsdk.webhook.sample.springboot.conversion;
+
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionReview;
+import io.javaoperatorsdk.webhook.conversion.AsyncConversionController;
+import io.javaoperatorsdk.webhook.conversion.ConversionController;
+
+import reactor.core.publisher.Mono;
+
+@RestController
+public class ConversionEndpoint {
+
+ public static final String CONVERSION_PATH = "convert";
+ public static final String ASYNC_CONVERSION_PATH = "async-convert";
+
+ private final ConversionController conversionController;
+ private final AsyncConversionController asyncConversionController;
+
+ public ConversionEndpoint(ConversionController conversionController,
+ AsyncConversionController asyncConversionController) {
+ this.conversionController = conversionController;
+ this.asyncConversionController = asyncConversionController;
+ }
+
+ @PostMapping(CONVERSION_PATH)
+ @ResponseBody
+ public ConversionReview convert(@RequestBody ConversionReview conversionReview) {
+ return conversionController.handle(conversionReview);
+ }
+
+ @PostMapping(ASYNC_CONVERSION_PATH)
+ @ResponseBody
+ public Mono convertAsync(@RequestBody ConversionReview conversionReview) {
+ return Mono.fromCompletionStage(asyncConversionController.handle(conversionReview));
+ }
+
+}
diff --git a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/AdmissionEndpointTest.java b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpointTest.java
similarity index 93%
rename from samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/AdmissionEndpointTest.java
rename to samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpointTest.java
index 1f7f983b..2036e84e 100644
--- a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/AdmissionEndpointTest.java
+++ b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/admission/AdmissionEndpointTest.java
@@ -1,4 +1,4 @@
-package io.javaoperatorsdk.webhook.sample.springboot;
+package io.javaoperatorsdk.webhook.sample.springboot.admission;
import java.io.IOException;
import java.nio.file.Files;
@@ -15,9 +15,9 @@
import org.springframework.web.reactive.function.BodyInserter;
import org.springframework.web.reactive.function.BodyInserters;
-import static io.javaoperatorsdk.webhook.sample.springboot.AdmissionEndpoint.*;
+import static io.javaoperatorsdk.webhook.sample.springboot.admission.AdmissionEndpoint.*;
-@Import(Config.class)
+@Import(AdmissionConfig.class)
@WebFluxTest(AdmissionEndpoint.class)
class AdmissionEndpointTest {
diff --git a/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/conversion/ConversionEndpointTest.java b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/conversion/ConversionEndpointTest.java
new file mode 100644
index 00000000..45ddbb06
--- /dev/null
+++ b/samples/spring-boot/src/test/java/io/javaoperatorsdk/webhook/sample/springboot/conversion/ConversionEndpointTest.java
@@ -0,0 +1,69 @@
+package io.javaoperatorsdk.webhook.sample.springboot.conversion;
+
+import java.io.IOException;
+import java.nio.file.Files;
+
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest;
+import org.springframework.context.annotation.Import;
+import org.springframework.core.io.Resource;
+import org.springframework.http.MediaType;
+import org.springframework.http.ReactiveHttpOutputMessage;
+import org.springframework.test.web.reactive.server.WebTestClient;
+import org.springframework.web.reactive.function.BodyInserter;
+import org.springframework.web.reactive.function.BodyInserters;
+
+import io.fabric8.kubernetes.api.model.apiextensions.v1.ConversionReview;
+import io.javaoperatorsdk.webhook.sample.commons.customresource.MultiVersionCustomResourceV2;
+
+import static io.javaoperatorsdk.webhook.sample.commons.mapper.V1Mapper.DEFAULT_ADDITIONAL_VALUE;
+import static io.javaoperatorsdk.webhook.sample.springboot.conversion.ConversionEndpoint.ASYNC_CONVERSION_PATH;
+import static io.javaoperatorsdk.webhook.sample.springboot.conversion.ConversionEndpoint.CONVERSION_PATH;
+import static org.assertj.core.api.Assertions.assertThat;
+
+@Import(ConversionConfig.class)
+@WebFluxTest(ConversionEndpoint.class)
+class ConversionEndpointTest {
+
+ @Autowired
+ private WebTestClient webClient;
+
+ @Value("classpath:conversion-request.json")
+ private Resource request;
+
+
+ @Test
+ void convert() {
+ testConversion(CONVERSION_PATH);
+ }
+
+ @Test
+ void asyncConvert() {
+ testConversion(ASYNC_CONVERSION_PATH);
+ }
+
+ public void testConversion(String path) {
+ webClient.post().uri("/" + path).contentType(MediaType.APPLICATION_JSON)
+ .body(request())
+ .exchange()
+ .expectStatus().isOk().expectBody(ConversionReview.class).consumeWith(res -> {
+ var review = res.getResponseBody();
+ var resource1 =
+ ((MultiVersionCustomResourceV2) review.getResponse().getConvertedObjects().get(0));
+ assertThat(review.getResponse().getConvertedObjects()).hasSize(2);
+ assertThat(resource1.getSpec().getAdditionalValue()).isEqualTo(DEFAULT_ADDITIONAL_VALUE);
+ assertThat(resource1.getMetadata().getName()).isEqualTo("resource1");
+ });
+ }
+
+ private BodyInserter request() {
+ try {
+ return BodyInserters.fromValue(new String(Files.readAllBytes(request.getFile().toPath())));
+ } catch (IOException e) {
+ throw new IllegalStateException(e);
+ }
+ }
+
+}
diff --git a/samples/spring-boot/src/test/resources/conversion-request.json b/samples/spring-boot/src/test/resources/conversion-request.json
new file mode 100644
index 00000000..bb07e07f
--- /dev/null
+++ b/samples/spring-boot/src/test/resources/conversion-request.json
@@ -0,0 +1,47 @@
+{
+ "apiVersion": "apiextensions.k8s.io/v1",
+ "kind": "ConversionReview",
+ "request": {
+
+ "uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
+
+ "desiredAPIVersion": "sample.javaoperatorsdk/v2",
+
+ "objects": [
+ {
+ "kind": "MultiVersionCustomResource",
+ "apiVersion": "sample.javaoperatorsdk/v1",
+ "metadata": {
+ "creationTimestamp": "2021-09-04T14:03:02Z",
+ "name": "resource1",
+ "namespace": "default",
+ "resourceVersion": "143",
+ "uid": "3415a7fc-162b-4300-b5da-fd6083580d66"
+ },
+ "spec": {
+ "value": 1
+ },
+ "status":{
+ "ready": true
+ }
+ },
+ {
+ "kind": "MultiVersionCustomResource",
+ "apiVersion": "sample.javaoperatorsdk/v1",
+ "metadata": {
+ "creationTimestamp": "2021-09-04T14:03:02Z",
+ "name": "resource2",
+ "namespace": "default",
+ "resourceVersion": "14344",
+ "uid": "1115a7fc-162b-4300-b5da-fd6083580d55"
+ },
+ "spec": {
+ "value": 2
+ },
+ "status":{
+ "ready": false
+ }
+ }
+ ]
+}
+}
\ No newline at end of file