diff --git a/core/deployment/src/main/java/io/quarkus/deployment/Capability.java b/core/deployment/src/main/java/io/quarkus/deployment/Capability.java index 71e8487466d73..59427926d868c 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/Capability.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/Capability.java @@ -65,7 +65,8 @@ public enum Capability { */ SMALLRYE_OPENTRACING, SPRING_WEB, - SMALLRYE_OPENAPI; + SMALLRYE_OPENAPI, + OPENSHIFT_CLIENT; /** * diff --git a/docs/src/main/asciidoc/writing-extensions.adoc b/docs/src/main/asciidoc/writing-extensions.adoc index 1d80b985edee7..e03093d159932 100644 --- a/docs/src/main/asciidoc/writing-extensions.adoc +++ b/docs/src/main/asciidoc/writing-extensions.adoc @@ -898,18 +898,6 @@ ExecutorBuildItem createExecutor( // <2> <1> Note the `optional` attribute. <2> This example is using recorder proxies; see the section on <> for more information. -==== Capabilities - -The `@BuildStep` annotation has a `providesCapabilities` property that can be used to provide capability information -to other extensions about what is present in the current application. Capabilities are simply strings that are used to -describe an extension. Capabilities should generally be named after an extensions root package, for example the transactions -extension will provide `io.quarkus.transactions`. - -To check if a capability is present you can inject the `io.quarkus.deployment.Capabilities` object and call -`isCapabilityPresent`. - -Capabilities should be used when checking for the presence of an extension rather than class path based checks. - ==== Application Archives The `@BuildStep` annotation can also register marker files that determine which archives on the class path are considered @@ -1354,6 +1342,9 @@ static class IsDevMode implements BooleanSupplier { } ---- +If you need to make your build step conditional on the presence or absence of another extension, you can +use <> for that. + [id='bytecode-recording'] === Bytecode Recording @@ -2150,6 +2141,7 @@ cd rest-json A _capability_ represents a technical capability that can be queried by other extensions. An extension may provide multiple capabilities and multiple extensions can provide the same capability. By default, capabilities are not displayed to users. +Capabilities should be used when checking for the presence of an extension rather than class path based checks. Capabilities can be registered in a <> method that produces a `CapabilityBuildItem`: diff --git a/extensions/kubernetes-client/deployment/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesClientProcessor.java b/extensions/kubernetes-client/deployment/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesClientProcessor.java index cd6d7eabfcbe5..cbefa1138ca5b 100644 --- a/extensions/kubernetes-client/deployment/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesClientProcessor.java +++ b/extensions/kubernetes-client/deployment/src/main/java/io/quarkus/kubernetes/client/deployment/KubernetesClientProcessor.java @@ -12,6 +12,8 @@ import org.jboss.logging.Logger; import io.quarkus.arc.deployment.AdditionalBeanBuildItem; +import io.quarkus.deployment.Capabilities; +import io.quarkus.deployment.Capability; import io.quarkus.deployment.Feature; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; @@ -24,6 +26,7 @@ import io.quarkus.deployment.util.JandexUtil; import io.quarkus.jackson.deployment.IgnoreJsonDeserializeClassBuildItem; import io.quarkus.kubernetes.client.runtime.KubernetesClientProducer; +import io.quarkus.kubernetes.client.runtime.KubernetesConfigProducer; import io.quarkus.kubernetes.spi.KubernetesRoleBindingBuildItem; public class KubernetesClientProcessor { @@ -38,10 +41,21 @@ public class KubernetesClientProcessor { private static final Logger log = Logger.getLogger(KubernetesClientProcessor.class.getName()); + @BuildStep + public void registerBeanProducers(BuildProducer additionalBeanBuildItemBuildItem, + Capabilities capabilities) { + // wire up the Config bean support + additionalBeanBuildItemBuildItem.produce(AdditionalBeanBuildItem.unremovableOf(KubernetesConfigProducer.class)); + // do not register our client producer if the openshift client is present, because it provides it too + if (capabilities.isMissing(Capability.OPENSHIFT_CLIENT)) { + // wire up the KubernetesClient bean support + additionalBeanBuildItemBuildItem.produce(AdditionalBeanBuildItem.unremovableOf(KubernetesClientProducer.class)); + } + } + @BuildStep public void process(ApplicationIndexBuildItem applicationIndex, CombinedIndexBuildItem combinedIndexBuildItem, BuildProducer sslNativeSupport, - BuildProducer additionalBeanBuildItemBuildItem, BuildProducer featureProducer, BuildProducer reflectiveClasses, BuildProducer reflectiveHierarchies, @@ -125,9 +139,6 @@ public void process(ApplicationIndexBuildItem applicationIndex, CombinedIndexBui // Enable SSL support by default sslNativeSupport.produce(new ExtensionSslNativeSupportBuildItem(Feature.KUBERNETES_CLIENT)); - - // wire up the KubernetesClient bean support - additionalBeanBuildItemBuildItem.produce(AdditionalBeanBuildItem.unremovableOf(KubernetesClientProducer.class)); } private void findWatchedClasses(final DotName implementor, final ApplicationIndexBuildItem applicationIndex, diff --git a/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientProducer.java b/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientProducer.java index d4129a4c561cc..e459973e3e10e 100644 --- a/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientProducer.java +++ b/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesClientProducer.java @@ -8,20 +8,12 @@ import io.fabric8.kubernetes.client.DefaultKubernetesClient; import io.fabric8.kubernetes.client.KubernetesClient; import io.quarkus.arc.DefaultBean; -import io.quarkus.runtime.TlsConfig; @Singleton public class KubernetesClientProducer { private KubernetesClient client; - @DefaultBean - @Singleton - @Produces - public Config config(KubernetesClientBuildConfig buildConfig, TlsConfig tlsConfig) { - return KubernetesClientUtils.createConfig(buildConfig, tlsConfig); - } - @DefaultBean @Singleton @Produces diff --git a/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesConfigProducer.java b/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesConfigProducer.java new file mode 100644 index 0000000000000..c188734bf1b9e --- /dev/null +++ b/extensions/kubernetes-client/runtime/src/main/java/io/quarkus/kubernetes/client/runtime/KubernetesConfigProducer.java @@ -0,0 +1,19 @@ +package io.quarkus.kubernetes.client.runtime; + +import javax.enterprise.inject.Produces; +import javax.inject.Singleton; + +import io.fabric8.kubernetes.client.Config; +import io.quarkus.arc.DefaultBean; +import io.quarkus.runtime.TlsConfig; + +@Singleton +public class KubernetesConfigProducer { + + @DefaultBean + @Singleton + @Produces + public Config config(KubernetesClientBuildConfig buildConfig, TlsConfig tlsConfig) { + return KubernetesClientUtils.createConfig(buildConfig, tlsConfig); + } +} diff --git a/extensions/openshift-client/deployment/src/main/java/io/quarkus/openshift/client/deployment/OpenShiftClientProcessor.java b/extensions/openshift-client/deployment/src/main/java/io/quarkus/openshift/client/deployment/OpenShiftClientProcessor.java index 4f01cd46bbc69..87243a2ee6559 100644 --- a/extensions/openshift-client/deployment/src/main/java/io/quarkus/openshift/client/deployment/OpenShiftClientProcessor.java +++ b/extensions/openshift-client/deployment/src/main/java/io/quarkus/openshift/client/deployment/OpenShiftClientProcessor.java @@ -1,9 +1,11 @@ package io.quarkus.openshift.client.deployment; import io.quarkus.arc.deployment.AdditionalBeanBuildItem; +import io.quarkus.deployment.Capability; import io.quarkus.deployment.Feature; import io.quarkus.deployment.annotations.BuildProducer; import io.quarkus.deployment.annotations.BuildStep; +import io.quarkus.deployment.builditem.CapabilityBuildItem; import io.quarkus.deployment.builditem.FeatureBuildItem; import io.quarkus.it.openshift.client.runtime.OpenShiftClientProducer; @@ -19,4 +21,9 @@ public void process(BuildProducer additionalBeanBuildIt public FeatureBuildItem feature() { return new FeatureBuildItem(Feature.OPENSHIFT_CLIENT); } + + @BuildStep + public CapabilityBuildItem capability() { + return new CapabilityBuildItem(Capability.OPENSHIFT_CLIENT); + } } diff --git a/integration-tests/openshift-client/src/main/java/io/quarkus/it/openshift/client/Routes.java b/integration-tests/openshift-client/src/main/java/io/quarkus/it/openshift/client/Routes.java index 0e4a7819eb84b..c2a2196d11e7d 100644 --- a/integration-tests/openshift-client/src/main/java/io/quarkus/it/openshift/client/Routes.java +++ b/integration-tests/openshift-client/src/main/java/io/quarkus/it/openshift/client/Routes.java @@ -1,24 +1,30 @@ package io.quarkus.it.openshift.client; +import javax.inject.Inject; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.core.Response; +import io.fabric8.kubernetes.client.KubernetesClient; import io.fabric8.openshift.client.OpenShiftClient; @Path("/route") public class Routes { - private final OpenShiftClient openshiftClient; + // make sure we can inject both aspects of it + @Inject + KubernetesClient kubernetesClient; - public Routes(OpenShiftClient openshiftClient) { - this.openshiftClient = openshiftClient; - } + @Inject + OpenShiftClient openshiftClient; @GET @Path("/{namespace}") public Response routes(@PathParam("namespace") String namespace) { + if (kubernetesClient != openshiftClient) { + return Response.serverError().entity("The clients are different").build(); + } return Response.ok(openshiftClient.routes().inNamespace(namespace).list().getItems()).build(); } }