From b27efeb57a7e84f731208de50c4ae2a2b7d36022 Mon Sep 17 00:00:00 2001 From: Marc Nuri Date: Fri, 9 Jun 2023 15:29:22 +0200 Subject: [PATCH] feat: static KubernetesResource class registration in synthetic bean Signed-off-by: Marc Nuri --- .../KubernetesResourceBuildStep.java | 52 +++++++++++++++++++ .../client/runtime/KubernetesResources.java | 18 +++++++ .../KubernetesSerializationRecorder.java | 14 +++++ .../KubernetesSerializationProducer.java | 8 ++- .../spi/KubernetesResourcesBuildItem.java | 17 ++++++ 5 files changed, 107 insertions(+), 2 deletions(-) create mode 100644 extensions/kubernetes-client/deployment-internal/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesResourceBuildStep.java create mode 100644 extensions/kubernetes-client/runtime-internal/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesResources.java create mode 100644 extensions/kubernetes-client/runtime-internal/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesSerializationRecorder.java create mode 100644 extensions/kubernetes-client/spi/src/main/java/io/quarkus/kubernetes/client/spi/KubernetesResourcesBuildItem.java diff --git a/extensions/kubernetes-client/deployment-internal/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesResourceBuildStep.java b/extensions/kubernetes-client/deployment-internal/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesResourceBuildStep.java new file mode 100644 index 00000000000000..7a370b4ccf970d --- /dev/null +++ b/extensions/kubernetes-client/deployment-internal/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesResourceBuildStep.java @@ -0,0 +1,52 @@ +package io.quarkus.kubernetes.client.deployment; + +import java.util.HashSet; +import java.util.ServiceLoader; +import java.util.Set; + +import jakarta.inject.Singleton; + +import org.jboss.jandex.AnnotationInstance; +import org.jboss.jandex.DotName; +import org.jboss.jandex.Type; + +import io.fabric8.kubernetes.api.model.KubernetesResource; +import io.quarkus.arc.deployment.AdditionalBeanBuildItem; +import io.quarkus.arc.deployment.SyntheticBeanBuildItem; +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.annotations.ExecutionTime; +import io.quarkus.deployment.annotations.Record; +import io.quarkus.kubernetes.client.runtime.KubernetesResources; +import io.quarkus.kubernetes.client.runtime.KubernetesSerializationRecorder; +import io.quarkus.kubernetes.client.spi.KubernetesResourcesBuildItem; + +public class KubernetesResourceBuildStep { + + @BuildStep + void scanKubernetesResourceClasses(BuildProducer kubernetesResourcesBuildItemBuildProducer) { + final Set> resourceClasses = new HashSet<>(); + final var serviceLoader = ServiceLoader.load(KubernetesResource.class); + for (var kr : serviceLoader) { + resourceClasses.add(kr.getClass()); + } + kubernetesResourcesBuildItemBuildProducer.produce( + new KubernetesResourcesBuildItem(resourceClasses.> toArray(Class[]::new))); + } + + @BuildStep + @Record(ExecutionTime.STATIC_INIT) + SyntheticBeanBuildItem kubernetesResourceClasses( + KubernetesSerializationRecorder recorder, + KubernetesResourcesBuildItem kubernetesResourcesBuildItem, + BuildProducer additionalBeans) { + additionalBeans.produce(AdditionalBeanBuildItem.unremovableOf(KubernetesResources.class)); + final var classArray = Type.create(DotName.createSimple(Class[].class.getName()), Type.Kind.ARRAY); + return SyntheticBeanBuildItem + .configure(Object.class).providerType(classArray).addType(classArray) + .scope(Singleton.class) + .qualifiers(AnnotationInstance.builder(KubernetesResources.class).build()) + .runtimeValue(recorder.initKubernetesResources(kubernetesResourcesBuildItem.getResourceClasses())) + .done(); + } +} diff --git a/extensions/kubernetes-client/runtime-internal/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesResources.java b/extensions/kubernetes-client/runtime-internal/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesResources.java new file mode 100644 index 00000000000000..bc3f527ace943a --- /dev/null +++ b/extensions/kubernetes-client/runtime-internal/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesResources.java @@ -0,0 +1,18 @@ +package io.quarkus.kubernetes.client.runtime; + +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.PARAMETER; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +import jakarta.inject.Qualifier; + +@Qualifier +@Retention(RUNTIME) +@Target({ METHOD, FIELD, PARAMETER, TYPE }) +public @interface KubernetesResources { +} diff --git a/extensions/kubernetes-client/runtime-internal/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesSerializationRecorder.java b/extensions/kubernetes-client/runtime-internal/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesSerializationRecorder.java new file mode 100644 index 00000000000000..c62477a9bdd7fa --- /dev/null +++ b/extensions/kubernetes-client/runtime-internal/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesSerializationRecorder.java @@ -0,0 +1,14 @@ +package io.quarkus.kubernetes.client.runtime; + +import io.fabric8.kubernetes.api.model.KubernetesResource; +import io.quarkus.runtime.RuntimeValue; +import io.quarkus.runtime.annotations.Recorder; + +@Recorder +public class KubernetesSerializationRecorder { + + public RuntimeValue[]> initKubernetesResources( + Class[] resources) { + return new RuntimeValue<>(resources); + } +} diff --git a/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesSerializationProducer.java b/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesSerializationProducer.java index e1b7690c92c92c..133885d41f6f4e 100644 --- a/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesSerializationProducer.java +++ b/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesSerializationProducer.java @@ -15,9 +15,13 @@ public class KubernetesSerializationProducer { @DefaultBean @Singleton @Produces - public KubernetesSerialization kubernetesSerialization(@KubernetesClientObjectMapper ObjectMapper objectMapper) { + public KubernetesSerialization kubernetesSerialization( + @KubernetesClientObjectMapper ObjectMapper objectMapper, + @KubernetesResources Class[] kubernetesResources) { final var kubernetesSerialization = new KubernetesSerialization(objectMapper, false); - KubernetesClientUtils.scanKubernetesResources().forEach(kubernetesSerialization::registerKubernetesResource); + for (var kubernetesResource : kubernetesResources) { + kubernetesSerialization.registerKubernetesResource(kubernetesResource); + } return kubernetesSerialization; } } diff --git a/extensions/kubernetes-client/spi/src/main/java/io/quarkus/kubernetes/client/spi/KubernetesResourcesBuildItem.java b/extensions/kubernetes-client/spi/src/main/java/io/quarkus/kubernetes/client/spi/KubernetesResourcesBuildItem.java new file mode 100644 index 00000000000000..171484c85581c1 --- /dev/null +++ b/extensions/kubernetes-client/spi/src/main/java/io/quarkus/kubernetes/client/spi/KubernetesResourcesBuildItem.java @@ -0,0 +1,17 @@ +package io.quarkus.kubernetes.client.spi; + +import io.fabric8.kubernetes.api.model.KubernetesResource; +import io.quarkus.builder.item.SimpleBuildItem; + +public final class KubernetesResourcesBuildItem extends SimpleBuildItem { + + private final Class[] resourceClasses; + + public KubernetesResourcesBuildItem(Class[] resourceClasses) { + this.resourceClasses = resourceClasses; + } + + public Class[] getResourceClasses() { + return resourceClasses; + } +}