From d171f13afe647f7c5b9523a6ea0c67a1d7aff9f8 Mon Sep 17 00:00:00 2001 From: Summers Pittman Date: Mon, 8 Nov 2021 19:55:07 -0500 Subject: [PATCH] feat: service binding support for service registry with application services --- .../apicurio-registry-avro/deployment/pom.xml | 1 + .../avro/ApicurioRegistryAvroProcessor.java | 34 +++++- ...viceRegistryBindingExtensionProcessor.java | 21 ++++ .../apicurio-registry-avro/runtime/pom.xml | 12 +- .../ServiceRegistryBindingConverter.java | 103 ++++++++++++++++++ ...ce.binding.runtime.ServiceBindingConverter | 1 + 6 files changed, 169 insertions(+), 3 deletions(-) create mode 100644 extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java create mode 100644 extensions/apicurio-registry-avro/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java create mode 100644 extensions/apicurio-registry-avro/runtime/src/main/resources/META-INF/services/io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConverter diff --git a/extensions/apicurio-registry-avro/deployment/pom.xml b/extensions/apicurio-registry-avro/deployment/pom.xml index e8bcbb53b9bc1e..388a8ad5b82fb8 100644 --- a/extensions/apicurio-registry-avro/deployment/pom.xml +++ b/extensions/apicurio-registry-avro/deployment/pom.xml @@ -23,6 +23,7 @@ io.quarkus quarkus-core-deployment + io.quarkus quarkus-avro-deployment diff --git a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java b/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java index bf9d58d3641422..6fb17761e78f2b 100644 --- a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java +++ b/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/avro/ApicurioRegistryAvroProcessor.java @@ -1,5 +1,8 @@ package io.quarkus.apicurio.registry.avro; +import java.io.IOException; + +import io.apicurio.rest.client.spi.ApicurioHttpClientProvider; import io.quarkus.deployment.Feature; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; @@ -8,6 +11,7 @@ import io.quarkus.deployment.builditem.ExtensionSslNativeSupportBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem; +import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem; import io.quarkus.vertx.deployment.VertxBuildItem; public class ApicurioRegistryAvroProcessor { @@ -24,7 +28,7 @@ public void apicurioRegistryAvro(BuildProducer reflect "io.apicurio.registry.serde.avro.AvroKafkaDeserializer", "io.apicurio.registry.serde.avro.AvroKafkaSerializer")); - reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, false, + reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, "io.apicurio.registry.serde.strategy.SimpleTopicIdStrategy", "io.apicurio.registry.serde.strategy.TopicIdStrategy", "io.apicurio.registry.serde.avro.DefaultAvroDatumProvider", @@ -32,12 +36,32 @@ public void apicurioRegistryAvro(BuildProducer reflect "io.apicurio.registry.serde.avro.strategy.RecordIdStrategy", "io.apicurio.registry.serde.avro.strategy.TopicRecordIdStrategy")); - reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, false, + reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, "io.apicurio.registry.serde.DefaultSchemaResolver", "io.apicurio.registry.serde.DefaultIdHandler", "io.apicurio.registry.serde.Legacy4ByteIdHandler", "io.apicurio.registry.serde.fallback.DefaultFallbackArtifactProvider", "io.apicurio.registry.serde.headers.DefaultHeadersHandler")); + + reflectiveClass.produce(new ReflectiveClassBuildItem(true, true, true, + "io.apicurio.rest.client.auth.exception.NotAuthorizedException", + "io.apicurio.rest.client.auth.exception.ForbiddenException", + "io.apicurio.rest.client.auth.exception.AuthException", + "io.apicurio.rest.client.auth.exception.AuthErrorHandler", + "io.apicurio.rest.client.auth.request.TokenRequestsProvider", + "io.apicurio.rest.client.request.Request", + "io.apicurio.rest.client.auth.AccessTokenResponse", + "io.apicurio.rest.client.auth.Auth", + "io.apicurio.rest.client.auth.BasicAuth", + "io.apicurio.rest.client.auth.OidcAuth")); + } + + @BuildStep + void registerSPIClient(BuildProducer services) throws IOException { + + services.produce( + new ServiceProviderBuildItem(ApicurioHttpClientProvider.class.getName(), + "io.apicurio.rest.client.VertxHttpClientProvider")); } @BuildStep @@ -45,4 +69,10 @@ public void apicurioRegistryAvro(BuildProducer reflect public void apicurioRegistryClient(VertxBuildItem vertx, ApicurioRegistryClient client) { client.setup(vertx.getVertx()); } + + @BuildStep + ExtensionSslNativeSupportBuildItem enableSslInNative() { + return new ExtensionSslNativeSupportBuildItem(Feature.APICURIO_REGISTRY_AVRO); + } + } diff --git a/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java b/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java new file mode 100644 index 00000000000000..c1835061bac21d --- /dev/null +++ b/extensions/apicurio-registry-avro/deployment/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingExtensionProcessor.java @@ -0,0 +1,21 @@ +package io.quarkus.apicurio.registry.avro.binding; + +import io.quarkus.apicurio.registry.binding.ServiceRegistryBindingConverter; +import io.quarkus.deployment.Capabilities; +import io.quarkus.deployment.Capability; +import io.quarkus.deployment.annotations.BuildProducer; +import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.nativeimage.ServiceProviderBuildItem; + +class ServiceRegistryBindingExtensionProcessor { + + @BuildStep + void registerServiceBinding(Capabilities capabilities, + BuildProducer serviceProvider) { + if (capabilities.isPresent(Capability.KUBERNETES_SERVICE_BINDING)) { + serviceProvider.produce( + new ServiceProviderBuildItem("io.quarkus.apicurio.registry.binding.ServiceRegistryBindingConverter", + ServiceRegistryBindingConverter.class.getName())); + } + } +} diff --git a/extensions/apicurio-registry-avro/runtime/pom.xml b/extensions/apicurio-registry-avro/runtime/pom.xml index a0ad9a498a8fea..8544a4c7a3069b 100644 --- a/extensions/apicurio-registry-avro/runtime/pom.xml +++ b/extensions/apicurio-registry-avro/runtime/pom.xml @@ -28,7 +28,12 @@ io.apicurio apicurio-common-rest-client-vertx - + + io.quarkus + quarkus-kubernetes-service-binding + true + + io.quarkus quarkus-core @@ -41,6 +46,11 @@ io.quarkus quarkus-vertx + + + org.apache.commons + commons-lang3 + diff --git a/extensions/apicurio-registry-avro/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java b/extensions/apicurio-registry-avro/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java new file mode 100644 index 00000000000000..1b931ac8bf4ef0 --- /dev/null +++ b/extensions/apicurio-registry-avro/runtime/src/main/java/io/quarkus/apicurio/registry/binding/ServiceRegistryBindingConverter.java @@ -0,0 +1,103 @@ +package io.quarkus.apicurio.registry.binding; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.logging.Logger; + +import org.apache.commons.lang3.StringUtils; +import org.eclipse.microprofile.config.Config; +import org.eclipse.microprofile.config.ConfigProvider; + +import io.quarkus.kubernetes.service.binding.runtime.ServiceBinding; +import io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConfigSource; +import io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConverter; + +public class ServiceRegistryBindingConverter implements ServiceBindingConverter { + + private static Logger LOG = Logger.getLogger(ServiceRegistryBindingConverter.class.getName()); + + private static final String INCOMING_PREFIX = "mp.messaging.incoming."; + private static final String OUTGOING_PREFIX = "mp.messaging.outgoing."; + + @Override + public Optional convert(List serviceBindings) { + var matchingByType = ServiceBinding.singleMatchingByType("serviceregistry", serviceBindings); + Config config = ConfigProvider.getConfig(); + if (matchingByType.isEmpty()) { + return Optional.empty(); + } + + var binding = matchingByType.get(); + + List channels = extractChannels(config); + + Map properties = new HashMap<>(); + + String registryUrl = binding.getProperties().get("registryUrl"); + if (registryUrl == null) { + registryUrl = binding.getProperties().get("registryurl"); + } + if (registryUrl != null) { + properties.put("mp.messaging.connector.smallrye-kafka.apicurio.registry.url", registryUrl); + } + + for (String channel : channels) { + + String prefix = channel; + + String oauthTokenUrl = binding.getProperties().get("oauthTokenUrl"); + if (oauthTokenUrl == null) { + oauthTokenUrl = binding.getProperties().get("oauthtokenurl"); + } + if (oauthTokenUrl != null) { + properties.put(prefix + "apicurio.auth.service.token.endpoint", oauthTokenUrl); + } + + String clientId = binding.getProperties().get("clientId"); + if (clientId == null) { + clientId = binding.getProperties().get("clientid"); + } + if (clientId != null) { + properties.put(prefix + "apicurio.auth.client.id", clientId); + } + + String clientSecret = binding.getProperties().get("clientSecret"); + if (clientSecret == null) { + clientSecret = binding.getProperties().get("clientsecret"); + } + if (clientSecret != null) { + properties.put(prefix + "apicurio.auth.client.secret", clientSecret); + } + if (registryUrl != null) { + properties.put(prefix + "apicurio.registry.url", registryUrl); + } + } + + return Optional.of(new ServiceBindingConfigSource("serviceregistry-k8s-service-binding-source", properties)); + } + + private List extractChannels(Config configIn) { + + var list = new ArrayList(); + + for (String propertyName : configIn.getPropertyNames()) { + if (propertyName.startsWith(INCOMING_PREFIX)) { + var channelAndProp = StringUtils.substringAfter(propertyName, INCOMING_PREFIX); + //remove property + var channelName = StringUtils.substringBefore(channelAndProp, "."); + if (!StringUtils.isBlank(channelName)) + list.add(INCOMING_PREFIX + channelName + "."); + } else if (propertyName.startsWith(OUTGOING_PREFIX)) { + var channelAndProp = StringUtils.substringAfter(propertyName, OUTGOING_PREFIX); + //remove property + var channelName = StringUtils.substringBefore(channelAndProp, "."); + if (!StringUtils.isBlank(channelName)) + list.add(OUTGOING_PREFIX + channelName + "."); + } + } + return list; + } +} diff --git a/extensions/apicurio-registry-avro/runtime/src/main/resources/META-INF/services/io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConverter b/extensions/apicurio-registry-avro/runtime/src/main/resources/META-INF/services/io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConverter new file mode 100644 index 00000000000000..e9f01713f3fde4 --- /dev/null +++ b/extensions/apicurio-registry-avro/runtime/src/main/resources/META-INF/services/io.quarkus.kubernetes.service.binding.runtime.ServiceBindingConverter @@ -0,0 +1 @@ +io.quarkus.apicurio.registry.binding.ServiceRegistryBindingConverter \ No newline at end of file