diff --git a/grpc/core/src/main/java/io/helidon/grpc/core/GrpcTlsDescriptor.java b/grpc/core/src/main/java/io/helidon/grpc/core/GrpcTlsDescriptor.java deleted file mode 100644 index 383fea49cca..00000000000 --- a/grpc/core/src/main/java/io/helidon/grpc/core/GrpcTlsDescriptor.java +++ /dev/null @@ -1,202 +0,0 @@ -/* - * Copyright (c) 2019, 2024 Oracle and/or its affiliates. - * - * 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.helidon.grpc.core; - -import io.helidon.common.configurable.Resource; -import io.helidon.config.Config; -import io.helidon.config.metadata.Configured; -import io.helidon.config.metadata.ConfiguredOption; - -/** - * GrpcTlsDescriptor contains details about configuring TLS of a {@link io.grpc.Channel}. - */ -public class GrpcTlsDescriptor { - - private final boolean enabled; - private final boolean jdkSSL; - private final Resource tlsCert; - private final Resource tlsKey; - private final Resource tlsCaCert; - - private GrpcTlsDescriptor(boolean enabled, boolean jdkSSL, Resource tlsCert, Resource tlsKey, Resource tlsCaCert) { - this.enabled = enabled; - this.jdkSSL = jdkSSL; - this.tlsCert = tlsCert; - this.tlsKey = tlsKey; - this.tlsCaCert = tlsCaCert; - } - - /** - * Return a new instance of {@link io.helidon.grpc.core.GrpcTlsDescriptor.Builder}. - * @return a new instance of {@link io.helidon.grpc.core.GrpcTlsDescriptor.Builder} - */ - public static Builder builder() { - return new Builder(); - } - - /** - * Return an instance of builder based on the specified external config. - * - * @param config external config - * @return an instance of builder - */ - public static Builder builder(Config config) { - return new Builder(config); - } - - /** - * Create an instance of a TLS configuration from external configuration source. - * - * @param config external config - * @return an instance of a TLS configuration - */ - public static GrpcTlsDescriptor create(Config config) { - return builder(config).build(); - } - - /** - * Check if TLS is enabled. If this is false, then none of the other configuration values are used. - * @return true if TLS is enabled; false otherwise - */ - public boolean isEnabled() { - return enabled; - } - - /** - * Check if JDK SSL has be used. Only used for TLS enabled server channels.A Ignored by client channel. - * @return true if JDK ssl has to be used; false otherwise - */ - public boolean isJdkSSL() { - return jdkSSL; - } - - /** - * Get the tlsCert path. Can be either client or server cert. - * @return the path to tls certificate - */ - public Resource tlsCert() { - return tlsCert; - } - - /** - * Get the client private key path. Can be either client or server private key. - * @return the path to tls private key - */ - public Resource tlsKey() { - return tlsKey; - } - - /** - * Get the CA (certificate authority) certificate path. - * @return the path to CA certificate - */ - public Resource tlsCaCert() { - return tlsCaCert; - } - - /** - * Builder to build a new instance of {@link GrpcTlsDescriptor}. - */ - @Configured - public static class Builder implements io.helidon.common.Builder { - - private boolean enabled = true; - private boolean jdkSSL; - private Resource tlsCert; - private Resource tlsKey; - private Resource tlsCaCert; - - private Builder() { - } - - private Builder(Config config) { - if (config == null) { - return; - } - - config.get("tls-cert.resource").as(Resource::create).ifPresent(this::tlsCert); - config.get("tls-key.resource").as(Resource::create).ifPresent(this::tlsKey); - config.get("tls-ca-cert.resource").as(Resource::create).ifPresent(this::tlsCaCert); - - this.jdkSSL = config.get("jdk-ssl").asBoolean().orElse(false); - this.enabled = config.get("enabled").asBoolean().orElse(true); - } - - /** - * Enable or disable TLS. If enabled is false, then the rest of the TLS configuration properties are ignored. - * @param enabled true to enable, false otherwise - * @return this instance for fluent API - */ - @ConfiguredOption(value = "true") - public Builder enabled(boolean enabled) { - this.enabled = enabled; - return this; - } - - /** - * Sets the type of SSL implementation to be used. - * @param jdkSSL true to use JDK based SSL, false otherwise - * @return this instance for fluent API - */ - @ConfiguredOption(key = "jdk-ssl", value = "false") - public Builder jdkSSL(boolean jdkSSL) { - this.jdkSSL = jdkSSL; - return this; - } - - /** - * Set the client tlsCert path. Required only if mutual auth is desired. - * @param tlsCert the path to client's certificate - * @return this instance for fluent API - */ - @ConfiguredOption(key = "tls-cert") - public Builder tlsCert(Resource tlsCert) { - this.tlsCert = tlsCert; - return this; - } - - /** - * Set the client private key path. Required only if mutual auth is desired. - * @param tlsKey the 's TLS private key - * @return this instance for fluent API - */ - @ConfiguredOption(key = "tls-key") - public Builder tlsKey(Resource tlsKey) { - this.tlsKey = tlsKey; - return this; - } - - /** - * Set the CA (certificate authority) certificate path. - * @param caCert the path to CA certificate - * @return this instance for fluent API - */ - @ConfiguredOption(key = "tls-ca-cert") - public Builder tlsCaCert(Resource caCert) { - this.tlsCaCert = caCert; - return this; - } - - /** - * Create and return a new instance of {@link GrpcTlsDescriptor}. - * @return a new instance of {@link GrpcTlsDescriptor} - */ - public GrpcTlsDescriptor build() { - return new GrpcTlsDescriptor(enabled, jdkSSL, tlsCert, tlsKey, tlsCaCert); - } - } -} diff --git a/microprofile/grpc/client/pom.xml b/microprofile/grpc/client/pom.xml index a8bee438fe5..6c7b1bc43b6 100644 --- a/microprofile/grpc/client/pom.xml +++ b/microprofile/grpc/client/pom.xml @@ -33,6 +33,10 @@ io.helidon.grpc helidon-grpc-core + + io.helidon.microprofile.grpc + helidon-microprofile-grpc-core + io.helidon.config helidon-config @@ -53,6 +57,14 @@ io.helidon.common helidon-common-tls + + jakarta.inject + jakarta.inject-api + + + jakarta.enterprise + jakarta.enterprise.cdi-api + io.helidon.webserver helidon-webserver-grpc diff --git a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/ChannelProducer.java b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/ChannelProducer.java new file mode 100644 index 00000000000..0d4f244fa07 --- /dev/null +++ b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/ChannelProducer.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019, 2024 Oracle and/or its affiliates. + * + * 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.helidon.microprofile.grpc.client; + +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.locks.ReentrantLock; + +import io.helidon.config.Config; + +import io.grpc.Channel; +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.inject.Produces; +import jakarta.enterprise.inject.spi.InjectionPoint; +import jakarta.inject.Inject; + +/** + * A producer of gRPC {@link io.grpc.Channel Channels}. + */ +@ApplicationScoped +public class ChannelProducer { + + private final GrpcChannelsProvider provider; + private final ReentrantLock lock = new ReentrantLock(); + private final Map channelMap = new HashMap<>(); + + /** + * Create a {@link ChannelProducer}. + * + * @param config the {@link io.helidon.config.Config} to use to configure + * the provided {@link io.grpc.Channel}s + */ + @Inject + ChannelProducer(Config config) { + provider = GrpcChannelsProvider.create(config.get("grpc")); + } + + /** + * Produces a gRPC {@link io.grpc.Channel}. + * + * @param injectionPoint the injection point + * @return a gRPC {@link io.grpc.Channel} + */ + @Produces + @GrpcChannel(name = GrpcChannelsProvider.DEFAULT_CHANNEL_NAME) + public Channel get(InjectionPoint injectionPoint) { + GrpcChannel qualifier = injectionPoint.getQualifiers() + .stream() + .filter(q -> q.annotationType().equals(GrpcChannel.class)) + .map(q -> (GrpcChannel) q) + .findFirst() + .orElse(null); + + String name = (qualifier == null) ? GrpcChannelsProvider.DEFAULT_CHANNEL_NAME : qualifier.name(); + return findChannel(name); + } + + /** + * Produces the default gRPC {@link io.grpc.Channel}. + * + * @return the default gRPC {@link io.grpc.Channel} + */ + @Produces + public Channel getDefaultChannel() { + return findChannel(GrpcChannelsProvider.DEFAULT_CHANNEL_NAME); + } + + /** + * Obtain the named {@link io.grpc.Channel}. + * + * @param name the channel name + * @return the named {@link io.grpc.Channel} + */ + public Channel findChannel(String name) { + try { + lock.lock(); + return channelMap.computeIfAbsent(name, provider::channel); + } finally { + lock.unlock(); + } + } +} diff --git a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/ClientMethodDescriptor.java b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/ClientMethodDescriptor.java index f61b0c0ec11..01a1260ac71 100644 --- a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/ClientMethodDescriptor.java +++ b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/ClientMethodDescriptor.java @@ -381,7 +381,6 @@ public Rules callCredentials(CallCredentials callCredentials) { return this; } - /** * Builds and returns a new instance of {@link ClientMethodDescriptor}. * @@ -405,10 +404,10 @@ public ClientMethodDescriptor build() { } return new ClientMethodDescriptor(name, - descriptor.build(), - interceptors, - callCredentials, - methodHandler); + descriptor.build(), + interceptors, + callCredentials, + methodHandler); } } diff --git a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/DelegatingBeanAttributes.java b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/DelegatingBeanAttributes.java new file mode 100644 index 00000000000..04333d9fd81 --- /dev/null +++ b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/DelegatingBeanAttributes.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2019, 2024 Oracle and/or its affiliates. + * + * 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.helidon.microprofile.grpc.client; + +import java.lang.annotation.Annotation; +import java.lang.reflect.Type; +import java.util.Collections; +import java.util.Objects; +import java.util.Set; + +import jakarta.enterprise.inject.spi.BeanAttributes; + +/** + * A {@link jakarta.enterprise.inject.spi.BeanAttributes} implementation. + * + * @param the class of the bean instance + */ +class DelegatingBeanAttributes implements BeanAttributes { + + private final BeanAttributes delegate; + private final Set types; + + /** + * Create a {@link DelegatingBeanAttributes}. + * + * @param delegate the {@link jakarta.enterprise.inject.spi.BeanAttributes} to delegate to + * @param types the {@link java.lang.reflect.Type}s for this bean + */ + private DelegatingBeanAttributes(BeanAttributes delegate, Set types) { + super(); + Objects.requireNonNull(delegate); + this.delegate = delegate; + this.types = Collections.unmodifiableSet(types); + } + + /** + * Create a {@link DelegatingBeanAttributes}. + * + * @param delegate the {@link jakarta.enterprise.inject.spi.BeanAttributes} to delegate to + * @param types the {@link java.lang.reflect.Type}s for this bean + */ + static DelegatingBeanAttributes create(BeanAttributes delegate, Set types) { + return new DelegatingBeanAttributes<>(delegate, types); + } + + @Override + public String getName() { + return this.delegate.getName(); + } + + @Override + public Set getQualifiers() { + return this.delegate.getQualifiers(); + } + + @Override + public Class getScope() { + return this.delegate.getScope(); + } + + @Override + public Set> getStereotypes() { + return this.delegate.getStereotypes(); + } + + @Override + public Set getTypes() { + if (types == null || types.isEmpty()) { + return this.delegate.getTypes(); + } else { + return types; + } + } + + @Override + public boolean isAlternative() { + return this.delegate.isAlternative(); + } + + @Override + public String toString() { + return this.delegate.toString(); + } +} diff --git a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcChannel.java b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcChannel.java new file mode 100644 index 00000000000..b0a56281c8e --- /dev/null +++ b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcChannel.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2019, 2024 Oracle and/or its affiliates. + * + * 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.helidon.microprofile.grpc.client; + +import java.io.Serial; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import jakarta.enterprise.util.AnnotationLiteral; +import jakarta.enterprise.util.Nonbinding; +import jakarta.inject.Qualifier; + +/** + * A qualifier annotation that can be used to specify the name of a configured gRPC + * channel to inject, or the name of the host to connect to, as described in + * {@link io.helidon.microprofile.grpc.client.GrpcChannelsProvider#channel(String)} + * documentation. + *

+ * For example: + * + *

+ *     @Inject
+ *     @GrpcChannel(name = "foo")
+ *     private Channel channel;
+ * 
+ * + * This annotation can also be specified at the injection point for a client proxy, + * in combination with the {@link GrpcProxy @GrpcProxy} annotation: + * + *
+ *     @Inject
+ *     @GrpcChannel(name = "foo")
+ *     @GrpcProxy
+ *     private FooServiceClient client;
+ * 
+ * + * Alternatively, if the client proxy should always use the same channel, it can + * be specified on the client interface instead: + * + *
+ *     @Grpc(name = "FooService")
+ *     @GrpcChannel(name = "foo")
+ *     public interface FooServiceClient {
+ *         ...
+ *     };
+ * 
+ * + */ +@Target({ElementType.TYPE, ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Qualifier +public @interface GrpcChannel { + /** + * The name of the configured channel or gRPC server host. + * + * @return name of the channel + */ + @Nonbinding String name(); + + /** + * An {@link jakarta.enterprise.util.AnnotationLiteral} for the + * {@link GrpcChannel} annotation. + */ + class Literal extends AnnotationLiteral implements GrpcChannel { + + /** + * The singleton instance of {@link io.helidon.microprofile.grpc.client.GrpcChannel.Literal}. + */ + public static final Literal INSTANCE = new Literal(); + + @Serial + private static final long serialVersionUID = 1L; + + @Override + public String name() { + return ""; + } + } +} diff --git a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcChannelDescriptor.java b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcChannelDescriptor.java index 6c14be5901c..93b3cf1ee9b 100644 --- a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcChannelDescriptor.java +++ b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcChannelDescriptor.java @@ -18,10 +18,10 @@ import java.util.Optional; +import io.helidon.common.tls.Tls; import io.helidon.config.metadata.Configured; import io.helidon.config.metadata.ConfiguredOption; import io.helidon.config.objectmapping.Value; -import io.helidon.grpc.core.GrpcTlsDescriptor; import io.grpc.NameResolver; @@ -30,20 +30,18 @@ */ public class GrpcChannelDescriptor { - private final boolean inProcessChannel; private final String host; private final int port; private final String target; - private final GrpcTlsDescriptor tlsDescriptor; + private final Tls tls; private final String loadBalancerPolicy; private final NameResolver.Factory nameResolver; private GrpcChannelDescriptor(Builder builder) { - this.inProcessChannel = builder.inProcessChannel(); this.target = builder.target(); this.host = builder.host(); this.port = builder.port(); - this.tlsDescriptor = builder.tlsDescriptor(); + this.tls = builder.tls(); this.loadBalancerPolicy = builder.loadBalancerPolicy(); this.nameResolver = builder.nameResolverFactory(); } @@ -57,14 +55,6 @@ public static Builder builder() { return new Builder(); } - /** - * Checks if this is a descriptor for building a in process {@link io.grpc.Channel}. - * @return true if this is a descriptor for building a in process {@link io.grpc.Channel} - */ - public boolean isInProcessChannel() { - return inProcessChannel; - } - /** * Get the host name to connect. * @@ -116,20 +106,12 @@ public Optional nameResolverFactory() { } /** - * Get the {@link io.helidon.grpc.core.GrpcTlsDescriptor}. If this method returns null or - * if {@code tlsDescriptor.isEnabled()} is false, then no TLS will be used (and none of the other configuration - * values from {@code tlsDescriptor} will be used). - *

- * If the {@link GrpcTlsDescriptor} has been set but the value of {@link io.helidon.grpc.core.GrpcTlsDescriptor#isEnabled()} - * returns {@code false} then an empty {@link Optional} will be returned. + * Get Tls instance. * - * @return the optional {@link io.helidon.grpc.core.GrpcTlsDescriptor} + * @return the optional {@link io.helidon.common.tls.Tls} */ - public Optional tlsDescriptor() { - if (tlsDescriptor != null && tlsDescriptor.isEnabled()) { - return Optional.of(tlsDescriptor); - } - return Optional.empty(); + public Optional tls() { + return Optional.ofNullable(tls); } /** @@ -137,25 +119,13 @@ public Optional tlsDescriptor() { */ @Configured public static class Builder implements io.helidon.common.Builder { - private boolean inProcessChannel; private String host = GrpcChannelsProvider.DEFAULT_HOST; private int port = GrpcChannelsProvider.DEFAULT_PORT; - private GrpcTlsDescriptor tlsDescriptor; + private Tls tls; private String target; private String loadBalancerPolicy; private NameResolver.Factory nameResolver; - /** - * Set the host name to connect. - * - * @return this instance for fluent API - */ - @Value(key = "inProcess", withDefault = GrpcChannelsProvider.DEFAULT_HOST) - public Builder inProcess() { - this.inProcessChannel = true; - return this; - } - /** * Set the target string, which can be either a valid {@link NameResolver} * compliant URI, or an authority string. @@ -200,23 +170,22 @@ public Builder port(int port) { } /** - * Set the GrpcTlsDescriptor. If {@code tlsDescriptor} is null or if the {@code tlsDescriptor.isEnabled()} is false, - * then no TLS will be used. - * @param tlsDescriptor the GrpcSslDescriptor + * Sets Tls. * + * @param tls the TLS instance * @return this instance for fluent API */ @ConfiguredOption(key = "tls") @Value(key = "tls") - public Builder sslDescriptor(GrpcTlsDescriptor tlsDescriptor) { - this.tlsDescriptor = tlsDescriptor; + public Builder tls(Tls tls) { + this.tls = tls; return this; } /** * Set the default load balancer policy name. - * @param policy the load balancer policy name * + * @param policy the load balancer policy name * @return this instance for fluent API * * @see io.grpc.ManagedChannelBuilder#defaultLoadBalancingPolicy(String) @@ -235,7 +204,6 @@ public Builder loadBalancerPolicy(String policy) { * method in the gRPC Java API. * * @return this instance for fluent API - * * @see io.grpc.ManagedChannelBuilder#nameResolverFactory(NameResolver.Factory) */ @Deprecated @@ -244,10 +212,6 @@ public Builder nameResolverFactory(NameResolver.Factory factory) { return this; } - boolean inProcessChannel() { - return inProcessChannel; - } - String host() { return host; } @@ -256,8 +220,8 @@ int port() { return port; } - GrpcTlsDescriptor tlsDescriptor() { - return tlsDescriptor; + Tls tls() { + return tls; } String target() { diff --git a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcChannelsProvider.java b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcChannelsProvider.java index 661dedda160..27124e46bd1 100644 --- a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcChannelsProvider.java +++ b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcChannelsProvider.java @@ -16,13 +16,13 @@ package io.helidon.microprofile.grpc.client; +import java.lang.reflect.Method; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import io.helidon.common.tls.Tls; import io.helidon.config.Config; -import io.helidon.grpc.core.GrpcTlsDescriptor; import io.helidon.webclient.grpc.GrpcClient; import io.grpc.CallOptions; @@ -30,6 +30,8 @@ import io.grpc.ClientCall; import io.grpc.ManagedChannel; import io.grpc.MethodDescriptor; +import jakarta.enterprise.inject.spi.CDI; +import jakarta.enterprise.inject.spi.Extension; /** * GrpcChannelsProvider is a factory for pre-configured gRPC Channel instances. @@ -125,33 +127,54 @@ public ManagedChannel channel(String name) { } GrpcChannelDescriptor chCfg = channelConfigs.computeIfAbsent(name, hostName -> GrpcChannelDescriptor.builder().host(name).build()); - return createChannel(chCfg); + return createChannel(name, chCfg); } Map channels() { return channelConfigs; } - ManagedChannel createChannel(GrpcChannelDescriptor descriptor) { - GrpcTlsDescriptor tlsDescriptor = descriptor.tlsDescriptor().orElse(null); - if (tlsDescriptor == null) { - throw new IllegalArgumentException("Missing TLS information in gRPC channel descriptor"); - } - // TODO mutual TLS - Tls clientTls = Tls.builder() - .trust(trust -> trust - .keystore(store -> store - .passphrase("password") - .trustStore(true) - .keystore(tlsDescriptor.tlsCaCert()))) - .build(); + ManagedChannel createChannel(String name, GrpcChannelDescriptor descriptor) { + /* + Tls clientTls = descriptor.tls().orElse(null); + if (clientTls == null) { + throw new IllegalArgumentException("Client TLS must be configured for gRPC proxy client"); + } + */ + + // TODO config object mapping issue + Config config = Config.global().get("grpc.channels"); + Tls clientTls = Tls.create(config.get(name + ".tls")); + + int port = descriptor.port(); + if (port <= 0) { + port = discoverServerPort(); + } GrpcClient grpcClient = GrpcClient.builder() .tls(clientTls) - .baseUri("https://" + descriptor.host() + ":" + descriptor.port()) + .baseUri("https://" + descriptor.host() + ":" + port) .build(); return new GrpcManagedChannel(grpcClient.channel()); } + /** + * TODO This code should be moved to a Junit test module. + * + * @return server port + */ + @SuppressWarnings("unchecked") + private static int discoverServerPort() { + try { + Class extClass = (Class) Class + .forName("io.helidon.microprofile.server.ServerCdiExtension"); + Extension extension = CDI.current().getBeanManager().getExtension(extClass); + Method m = extension.getClass().getMethod("port", String.class); + return (int) m.invoke(extension, new Object[] {"@default"}); + } catch (ReflectiveOperationException e) { + return 0; + } + } + /** * A managed channel wrapper over a {@link GrpcClient} channel. */ @@ -162,6 +185,7 @@ private static class GrpcManagedChannel extends ManagedChannel { GrpcManagedChannel(Channel delegate) { this.delegate = delegate; } + @Override public ManagedChannel shutdown() { return this; diff --git a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcClientBuilder.java b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcClientBuilder.java new file mode 100644 index 00000000000..feed93e8fa2 --- /dev/null +++ b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcClientBuilder.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2019, 2024 Oracle and/or its affiliates. + * + * 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.helidon.microprofile.grpc.client; + +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.logging.Level; +import java.util.logging.Logger; + +import io.helidon.common.Builder; +import io.helidon.grpc.core.MethodHandler; +import io.helidon.microprofile.grpc.core.AbstractServiceBuilder; +import io.helidon.microprofile.grpc.core.AnnotatedMethod; +import io.helidon.microprofile.grpc.core.AnnotatedMethodList; +import io.helidon.microprofile.grpc.core.GrpcMarshaller; +import io.helidon.microprofile.grpc.core.GrpcMethod; +import io.helidon.microprofile.grpc.core.Instance; +import io.helidon.microprofile.grpc.core.ModelHelper; + +/** + * A builder for constructing a {@link io.helidon.microprofile.grpc.client.ClientServiceDescriptor.Builder} instances + * from an annotated POJO. + */ +class GrpcClientBuilder extends AbstractServiceBuilder + implements Builder { + + private static final Logger LOGGER = Logger.getLogger(GrpcClientBuilder.class.getName()); + + /** + * Create a {@link GrpcClientBuilder} for a given gRPC service class. + * + * @param serviceClass gRPC service (handler) class. + * @param instance the target instance to call gRPC handler methods on + * @throws NullPointerException if the service or instance parameters are null + */ + private GrpcClientBuilder(Class serviceClass, Supplier instance) { + super(serviceClass, instance); + } + + /** + * Create a {@link GrpcClientBuilder} for a given gRPC service. + * + * @param service the service to call gRPC handler methods on + * @throws NullPointerException if the service is null + * @return a {@link GrpcClientBuilder} + */ + static GrpcClientBuilder create(Object service) { + return new GrpcClientBuilder(service.getClass(), Instance.singleton(service)); + } + + /** + * Create a {@link GrpcClientBuilder} for a given gRPC service class. + * + * @param serviceClass gRPC service (handler) class. + * @throws NullPointerException if the service class is null + * @return a {@link GrpcClientBuilder} + */ + static GrpcClientBuilder create(Class serviceClass) { + return new GrpcClientBuilder(Objects.requireNonNull(serviceClass), createInstanceSupplier(serviceClass)); + } + + /** + * Create a new resource model builder for the introspected class. + *

+ * The model returned is filled with the introspected data. + *

+ * + * @return new resource model builder for the introspected class. + */ + @Override + public ClientServiceDescriptor.Builder build() { + checkForNonPublicMethodIssues(); + + Class annotatedServiceClass = annotatedServiceClass(); + AnnotatedMethodList methodList = AnnotatedMethodList.create(annotatedServiceClass); + String name = determineServiceName(annotatedServiceClass); + + ClientServiceDescriptor.Builder builder = ClientServiceDescriptor.builder(serviceClass()) + .name(name) + .marshallerSupplier(getMarshallerSupplier()); + + addServiceMethods(builder, methodList); + + LOGGER.log(Level.FINEST, () -> String.format("A new gRPC service was created by ServiceModeller: %s", builder)); + + return builder; + } + + /** + * Add methods to the {@link io.helidon.microprofile.grpc.client.ClientServiceDescriptor.Builder}. + * + * @param builder the {@link io.helidon.microprofile.grpc.client.ClientServiceDescriptor.Builder} to add the method to + * @param methodList the list of methods to add + */ + private void addServiceMethods(ClientServiceDescriptor.Builder builder, AnnotatedMethodList methodList) { + for (AnnotatedMethod am : methodList.withAnnotation(GrpcMethod.class)) { + addServiceMethod(builder, am); + } + for (AnnotatedMethod am : methodList.withMetaAnnotation(GrpcMethod.class)) { + addServiceMethod(builder, am); + } + } + + /** + * Add a method to the {@link io.helidon.microprofile.grpc.client.ClientServiceDescriptor.Builder}. + *

+ * The method configuration will be determined by the annotations present on the + * method and the method signature. + * + * @param builder the {@link io.helidon.microprofile.grpc.client.ClientServiceDescriptor.Builder} to add the method to + * @param method the {@link io.helidon.microprofile.grpc.core.AnnotatedMethod} representing the method to add + */ + private void addServiceMethod(ClientServiceDescriptor.Builder builder, AnnotatedMethod method) { + GrpcMethod annotation = method.firstAnnotationOrMetaAnnotation(GrpcMethod.class); + String name = determineMethodName(method, annotation); + + MethodHandler handler = handlerSuppliers().stream() + .filter(supplier -> supplier.supplies(method)) + .findFirst() + .map(supplier -> supplier.get(name, method, instanceSupplier())) + .orElseThrow(() -> new IllegalArgumentException("Cannot locate a method handler supplier for method " + method)); + + Class requestType = handler.getRequestType(); + Class responseType = handler.getResponseType(); + AnnotatedMethodConfigurer configurer = new AnnotatedMethodConfigurer(method, requestType, responseType, handler); + + switch (annotation.type()) { + case UNARY: + builder.unary(name, configurer); + break; + case CLIENT_STREAMING: + builder.clientStreaming(name, configurer); + break; + case SERVER_STREAMING: + builder.serverStreaming(name, configurer); + break; + case BIDI_STREAMING: + builder.bidirectional(name, configurer); + break; + case UNKNOWN: + default: + LOGGER.log(Level.SEVERE, () -> "Unrecognized method type " + annotation.type()); + } + } + + /** + * A {@link java.util.function.Consumer} of {@link io.helidon.microprofile.grpc.client.ClientMethodDescriptor.Rules} + * that applies configuration changes based on annotations present on the gRPC + * method. + */ + private static class AnnotatedMethodConfigurer + implements Consumer { + + private final AnnotatedMethod method; + private final Class requestType; + private final Class responseType; + private final MethodHandler methodHandler; + + private AnnotatedMethodConfigurer(AnnotatedMethod method, + Class requestType, + Class responseType, + MethodHandler methodHandler) { + this.method = method; + this.requestType = requestType; + this.responseType = responseType; + this.methodHandler = methodHandler; + } + + @Override + public void accept(ClientMethodDescriptor.Rules config) { + config.requestType(requestType) + .responseType(responseType) + .methodHandler(methodHandler); + + if (method.isAnnotationPresent(GrpcMarshaller.class)) { + config.marshallerSupplier(ModelHelper.getMarshallerSupplier(method.getAnnotation(GrpcMarshaller.class))); + } + } + } +} diff --git a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcClientCdiExtension.java b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcClientCdiExtension.java new file mode 100644 index 00000000000..d67659edc1b --- /dev/null +++ b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcClientCdiExtension.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2019, 2024 Oracle and/or its affiliates. + * + * 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.helidon.microprofile.grpc.client; + +import java.lang.reflect.Type; +import java.util.HashSet; +import java.util.Set; + +import jakarta.enterprise.event.Observes; +import jakarta.enterprise.inject.spi.AfterBeanDiscovery; +import jakarta.enterprise.inject.spi.Annotated; +import jakarta.enterprise.inject.spi.AnnotatedMethod; +import jakarta.enterprise.inject.spi.AnnotatedType; +import jakarta.enterprise.inject.spi.BeanAttributes; +import jakarta.enterprise.inject.spi.BeanManager; +import jakarta.enterprise.inject.spi.BeforeBeanDiscovery; +import jakarta.enterprise.inject.spi.Extension; +import jakarta.enterprise.inject.spi.ProcessInjectionPoint; +import jakarta.enterprise.inject.spi.ProducerFactory; + +/** + * A CDI extension to add gRPC client functionality. + */ +public class GrpcClientCdiExtension implements Extension { + + private final Set proxyTypes = new HashSet<>(); + + /** + * Adds beans to the bean manager. + * + * @param event before bean discovery event + */ + public void addBeans(@Observes BeforeBeanDiscovery event) { + event.addAnnotatedType(ChannelProducer.class, ChannelProducer.class.getName()); + } + + /** + * Process injection points. + *

+ * In this method injection points that have the {@link GrpcProxy} are processed + * and their types are stored so that in the {@link #afterBean( + *jakarta.enterprise.inject.spi.AfterBeanDiscovery, jakarta.enterprise.inject.spi.BeanManager)} + * we can manually create a producer for the correct service proxy type. + * + * @param pip the injection point + * @param the declared type of the injection point. + * @param the bean class of the bean that declares the injection point + */ + public void gatherApplications(@Observes ProcessInjectionPoint pip) { + Annotated annotated = pip.getInjectionPoint().getAnnotated(); + if (annotated.isAnnotationPresent(GrpcProxy.class)) { + Type type = pip.getInjectionPoint().getType(); + proxyTypes.add(type); + } + } + + /** + * Process the previously captured {@link GrpcProxy} injection points. + *

+ * For each {@link GrpcProxy} injection point we create a producer bean + * for the required type. + * + * @param event the {@link jakarta.enterprise.inject.spi.AfterBeanDiscovery} event + * @param beanManager the CDI bean manager + */ + public void afterBean(@Observes AfterBeanDiscovery event, BeanManager beanManager) { + AnnotatedType producerType = beanManager.createAnnotatedType(GrpcProxyProducer.class); + AnnotatedMethod producerMethod = producerType.getMethods() + .stream() + .filter(m -> m.isAnnotationPresent(GrpcProxy.class)) + .filter(m -> m.isAnnotationPresent(GrpcChannel.class)) + .findFirst() + .orElse(null); + if (producerMethod != null) { + for (Type type : proxyTypes) { + addProducerBean(event, beanManager, producerMethod, type); + } + } + } + + private void addProducerBean(AfterBeanDiscovery event, + BeanManager beanManager, + AnnotatedMethod producerMethod, + Type type) { + BeanAttributes producerAttributes = beanManager.createBeanAttributes(producerMethod); + ProducerFactory factory = beanManager.getProducerFactory(producerMethod, null); + Set types = Set.of(Object.class, type); + BeanAttributes beanAttributes = DelegatingBeanAttributes.create(producerAttributes, types); + event.addBean(beanManager.createBean(beanAttributes, GrpcProxyProducer.class, factory)); + } +} diff --git a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcProxy.java b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcProxy.java new file mode 100644 index 00000000000..3adc9df56be --- /dev/null +++ b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcProxy.java @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019, 2024 Oracle and/or its affiliates. + * + * 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.helidon.microprofile.grpc.client; + +import java.io.Serial; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import jakarta.enterprise.util.AnnotationLiteral; +import jakarta.inject.Qualifier; + +/** + * A qualifier annotation used to mark an injection point for + * a gRPC service client proxy. + */ +@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) +@Retention(RetentionPolicy.RUNTIME) +@Qualifier +public @interface GrpcProxy { + + /** + * An {@link jakarta.enterprise.util.AnnotationLiteral} for the + * {@link io.helidon.microprofile.grpc.client.GrpcProxy} annotation. + */ + class Literal extends AnnotationLiteral implements GrpcProxy { + + /** + * The singleton instance of {@link io.helidon.microprofile.grpc.client.GrpcProxy.Literal}. + */ + public static final Literal INSTANCE = new Literal(); + + @Serial + private static final long serialVersionUID = 1L; + } +} diff --git a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcProxyBuilder.java b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcProxyBuilder.java new file mode 100644 index 00000000000..d95d7593e86 --- /dev/null +++ b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcProxyBuilder.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2019, 2024 Oracle and/or its affiliates. + * + * 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.helidon.microprofile.grpc.client; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +import io.helidon.common.Builder; + +import io.grpc.Channel; + +/** + * A builder for gRPC clients dynamic proxies. + * + * @param the type of the interface to be proxied + */ +public class GrpcProxyBuilder implements Builder, T> { + + private static final Map, ClientServiceDescriptor> DESCRIPTORS = new ConcurrentHashMap<>(); + + private final GrpcServiceClient client; + + private final Class type; + + private GrpcProxyBuilder(GrpcServiceClient client, Class type) { + this.client = client; + this.type = type; + } + + /** + * Create a {@code GrpcProxyBuilder} that can build gRPC dynamic proxies + * for a given gRPC service interface. + *

+ * The class passed to this method should be properly annotated with + * {@link io.helidon.microprofile.grpc.core.Grpc} and + * {@link io.helidon.microprofile.grpc.core.GrpcMethod} annotations + * so that the proxy can properly route calls to the server. + * + * @param channel the {@link io.grpc.Channel} to connect to the server + * @param type the service type + * @param the service type + * @return a {@link io.helidon.microprofile.grpc.client.GrpcProxyBuilder} that can build dynamic proxies + * for the gRPC service + */ + public static GrpcProxyBuilder create(Channel channel, Class type) { + ClientServiceDescriptor descriptor = DESCRIPTORS.computeIfAbsent(type, GrpcProxyBuilder::createDescriptor); + return new GrpcProxyBuilder<>(GrpcServiceClient.builder(channel, descriptor).build(), type); + } + + /** + * Build a gRPC client dynamic proxy of the required type. + * + * @return a gRPC client dynamic proxy + */ + @Override + public T build() { + return client.proxy(type); + } + + private static ClientServiceDescriptor createDescriptor(Class type) { + GrpcClientBuilder builder = GrpcClientBuilder.create(type); + ClientServiceDescriptor.Builder descriptorBuilder = builder.build(); + return descriptorBuilder.build(); + } +} diff --git a/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcProxyProducer.java b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcProxyProducer.java new file mode 100644 index 00000000000..86ab53f2395 --- /dev/null +++ b/microprofile/grpc/client/src/main/java/io/helidon/microprofile/grpc/client/GrpcProxyProducer.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019, 2024 Oracle and/or its affiliates. + * + * 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.helidon.microprofile.grpc.client; + +import io.helidon.microprofile.grpc.core.ModelHelper; + +import io.grpc.Channel; +import jakarta.enterprise.inject.spi.InjectionPoint; + +/** + * A utility class of gRPC CDI producer stubs. + *

+ * The methods in this class are not real CDI producer methods, + * they act as templates that the {@link io.helidon.microprofile.grpc.client.GrpcClientCdiExtension} + * will use to create producers on the fly as injection points + * are observed. + */ +class GrpcProxyProducer { + + private GrpcProxyProducer() { + } + + /** + * A CDI producer method that produces a client proxy for a gRPC service that + * will connect to the server using the channel specified via + * {@link io.helidon.microprofile.grpc.client.GrpcChannel} + * annotation on the proxy interface or injection point, or the default + * {@link io.grpc.Channel}. + *

+ * This is not a real producer method but is used as a stub by the gRPC client + * CDI extension to create real producers as injection points are discovered. + * + * @param injectionPoint the injection point where the client proxy is to be injected + * @return a gRPC client proxy + */ + @GrpcProxy + @GrpcChannel(name = GrpcChannelsProvider.DEFAULT_CHANNEL_NAME) + static Object proxyUsingNamedChannel(InjectionPoint injectionPoint, ChannelProducer producer) { + Class type = ModelHelper.getGenericType(injectionPoint.getType()); + + String channelName; + if (injectionPoint.getAnnotated().isAnnotationPresent(GrpcChannel.class)) { + channelName = injectionPoint.getAnnotated().getAnnotation(GrpcChannel.class).name(); + } else { + channelName = type.isAnnotationPresent(GrpcChannel.class) + ? type.getAnnotation(GrpcChannel.class).name() + : GrpcChannelsProvider.DEFAULT_CHANNEL_NAME; + } + + Channel channel = producer.findChannel(channelName); + GrpcProxyBuilder builder = GrpcProxyBuilder.create(channel, type); + + return builder.build(); + } +} diff --git a/microprofile/grpc/client/src/main/java/module-info.java b/microprofile/grpc/client/src/main/java/module-info.java index 5f2f6daca2e..e6b486e2a1f 100644 --- a/microprofile/grpc/client/src/main/java/module-info.java +++ b/microprofile/grpc/client/src/main/java/module-info.java @@ -14,8 +14,10 @@ * limitations under the License. */ +import io.helidon.microprofile.grpc.client.GrpcClientCdiExtension; + /** - * gRPC microprofile client module + * gRPC microprofile client module. */ module io.helidon.microprofile.grpc.client { @@ -26,8 +28,17 @@ requires io.helidon.config.objectmapping; requires io.helidon.webclient.grpc; requires io.helidon.common.tls; + requires io.helidon.microprofile.grpc.core; - requires transitive io.helidon.grpc.core; requires io.grpc; + requires jakarta.cdi; + requires jakarta.inject; + requires java.logging; + + requires transitive io.helidon.grpc.core; + + exports io.helidon.microprofile.grpc.client; + + provides jakarta.enterprise.inject.spi.Extension with GrpcClientCdiExtension; } \ No newline at end of file diff --git a/microprofile/grpc/client/src/test/java/io/helidon/microprofile/grpc/client/EchoServiceTest.java b/microprofile/grpc/client/src/test/java/io/helidon/microprofile/grpc/client/EchoServiceTest.java index 51a9edb9eac..8eca61e4e42 100644 --- a/microprofile/grpc/client/src/test/java/io/helidon/microprofile/grpc/client/EchoServiceTest.java +++ b/microprofile/grpc/client/src/test/java/io/helidon/microprofile/grpc/client/EchoServiceTest.java @@ -29,6 +29,7 @@ import io.helidon.microprofile.grpc.server.GrpcMpCdiExtension; import io.helidon.microprofile.testing.junit5.AddBean; import io.helidon.microprofile.testing.junit5.AddExtension; +import io.helidon.microprofile.testing.junit5.Configuration; import io.helidon.microprofile.testing.junit5.HelidonTest; import io.helidon.webclient.grpc.GrpcClient; @@ -45,11 +46,16 @@ @AddBean(EchoServiceTest.EchoService.class) @AddBean(JavaMarshaller.Supplier.class) @AddExtension(GrpcMpCdiExtension.class) +@AddExtension(GrpcClientCdiExtension.class) class EchoServiceTest { @Inject private WebTarget webTarget; + @Inject + @GrpcProxy + private EchoServiceClient proxyClient; + @Test void testEcho() throws InterruptedException, ExecutionException, TimeoutException { Tls clientTls = Tls.builder() @@ -90,17 +96,32 @@ public void onCompleted() { assertThat(future.get(5, TimeUnit.SECONDS), is("Howdy")); } + @Test + void testEchoInject() throws InterruptedException, ExecutionException, TimeoutException { + CompletableFuture future = new CompletableFuture<>(); + StreamObserver observer = new StreamObserver<>() { + @Override + public void onNext(String value) { + future.complete(value); + } + + @Override + public void onError(Throwable t) { + } + + @Override + public void onCompleted() { + } + }; + proxyClient.echo("Howdy", observer); + assertThat(future.get(5, TimeUnit.SECONDS), is("Howdy")); + } + @Grpc + @GrpcMarshaller("java") public static class EchoService { - /** - * Echo the message back to the caller. - * - * @param request the echo request containing the message to echo - * @param observer the call response - */ @Unary(name = "Echo") - @GrpcMarshaller("java") public void echo(String request, StreamObserver observer) { try { complete(observer, request); @@ -109,4 +130,13 @@ public void echo(String request, StreamObserver observer) { } } } + + @Grpc(name = "EchoService") + @GrpcMarshaller("java") + @GrpcChannel(name = "echo-channel") + public interface EchoServiceClient { + + @Unary(name = "Echo") + void echo(String request, StreamObserver observer); + } } diff --git a/microprofile/grpc/client/src/test/java/io/helidon/microprofile/grpc/client/GrpcChannelsProviderTest.java b/microprofile/grpc/client/src/test/java/io/helidon/microprofile/grpc/client/GrpcChannelsProviderTest.java deleted file mode 100644 index 62d5d97b41b..00000000000 --- a/microprofile/grpc/client/src/test/java/io/helidon/microprofile/grpc/client/GrpcChannelsProviderTest.java +++ /dev/null @@ -1,252 +0,0 @@ -/* - * Copyright (c) 2019, 2024 Oracle and/or its affiliates. - * - * 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.helidon.microprofile.grpc.client; - -import java.util.Optional; - -import io.helidon.common.configurable.Resource; -import io.helidon.config.Config; -import io.helidon.config.ConfigSources; -import io.helidon.grpc.core.GrpcTlsDescriptor; - -import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.Test; - -import static org.hamcrest.CoreMatchers.endsWith; -import static org.hamcrest.CoreMatchers.equalTo; -import static org.hamcrest.CoreMatchers.hasItems; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.hamcrest.CoreMatchers.nullValue; -import static org.hamcrest.CoreMatchers.sameInstance; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.mockito.Mockito.mock; - -@SuppressWarnings("deprecation") -public class GrpcChannelsProviderTest { - - private static final String CLIENT_CERT = "ssl/clientCert.pem"; - private static final String CLIENT_KEY = "ssl/clientKey.pem"; - private static final String CA_CERT = "ssl/ca.pem"; - - private static final String DEFAULT_HOST_PORT_CFG = "default_host_port"; - private static final String DEFAULT_HOST_CFG = "default_host"; - private static final String DEFAULT_PORT_CFG = "default_port"; - private static final String DEFAULT_HOST_PORT_SSL_DISABLED_CFG = "default_host_port_ssl_disabled"; - private static final String DEFAULT_HOST_SSL_ONE_WAY_CFG = "default_host_ssl_one_way"; - private static final String DEFAULT_PORT_SSL_CFG = "default_port_ssl"; - private static final String DEFAULT_HOST = "localhost"; - private static final int DEFAULT_PORT = 1408; - private static GrpcChannelsProvider grpcConfig; - - @BeforeAll - public static void initGrpcConfig() { - Config cfg = Config.create(ConfigSources.classpath("test-client-config.yaml")); - grpcConfig = GrpcChannelsProvider.create(cfg.get("grpc")); - } - - @Test - public void testDefaultChannelConfiguration() { - GrpcChannelDescriptor cfg = GrpcChannelDescriptor.builder().build(); - assertThat(cfg.host(), equalTo(DEFAULT_HOST)); - assertThat(cfg.port(), equalTo(DEFAULT_PORT)); - assertThat(cfg.tlsDescriptor().isPresent(), is(false)); - assertThat(cfg.target().isPresent(), is(false)); - assertThat(cfg.loadBalancerPolicy().isPresent(), is(false)); - assertThat(cfg.nameResolverFactory().isPresent(), is(false)); - } - - @Test - public void testChannelConfigurationWithHost() { - GrpcChannelDescriptor cfg = GrpcChannelDescriptor.builder().host("abc.com").build(); - assertThat(cfg.host(), equalTo("abc.com")); - assertThat(cfg.port(), equalTo(DEFAULT_PORT)); - assertThat(cfg.tlsDescriptor().isPresent(), is(false)); - assertThat(cfg.target().isPresent(), is(false)); - assertThat(cfg.loadBalancerPolicy().isPresent(), is(false)); - assertThat(cfg.nameResolverFactory().isPresent(), is(false)); - } - - @Test - public void testChannelConfigurationWithPort() { - GrpcChannelDescriptor cfg = GrpcChannelDescriptor.builder().port(4096).build(); - assertThat(cfg.host(), equalTo("localhost")); - assertThat(cfg.port(), equalTo(4096)); - assertThat(cfg.tlsDescriptor().isPresent(), is(false)); - assertThat(cfg.target().isPresent(), is(false)); - assertThat(cfg.loadBalancerPolicy().isPresent(), is(false)); - assertThat(cfg.nameResolverFactory().isPresent(), is(false)); - } - - @Test - public void testChannelConfigurationWithDefaultSsl() { - GrpcChannelDescriptor cfg = GrpcChannelDescriptor.builder() - .sslDescriptor(GrpcTlsDescriptor.builder().build()) - .build(); - assertThat(cfg.host(), equalTo("localhost")); - assertThat(cfg.port(), equalTo(1408)); - Optional descriptor = cfg.tlsDescriptor(); - assertThat(descriptor.isPresent(), is(true)); - assertThat(descriptor.get().isEnabled(), is(true)); - assertThat(cfg.target().isPresent(), is(false)); - assertThat(cfg.loadBalancerPolicy().isPresent(), is(false)); - assertThat(cfg.nameResolverFactory().isPresent(), is(false)); - } - - @Test - public void testChannelConfigurationWithSslConfig() { - Resource certResource = mock(Resource.class); - Resource keyResource = mock(Resource.class); - Resource trustResource = mock(Resource.class); - - GrpcChannelDescriptor cfg = GrpcChannelDescriptor.builder() - .sslDescriptor( - GrpcTlsDescriptor.builder() - .tlsCaCert(trustResource) - .tlsCert(certResource) - .tlsKey(keyResource) - .build()) - .build(); - assertThat(cfg.host(), equalTo("localhost")); - assertThat(cfg.port(), equalTo(1408)); - Optional descriptor = cfg.tlsDescriptor(); - assertThat(descriptor.isPresent(), is(true)); - GrpcTlsDescriptor tlsDescriptor = descriptor.get(); - assertThat(tlsDescriptor.isEnabled(), is(true)); - assertThat(tlsDescriptor.tlsCaCert(), is(sameInstance(trustResource))); - assertThat(tlsDescriptor.tlsCert(), is(sameInstance(certResource))); - assertThat(tlsDescriptor.tlsKey(), is(sameInstance(keyResource))); - } - - @Test - public void testChannelWithTarget() { - String target = "dns://127.0.0.1:22"; - GrpcChannelDescriptor cfg = GrpcChannelDescriptor.builder() - .target(target) - .build(); - assertThat(cfg.target().isPresent(), is(true)); - assertThat(cfg.target().get(), is(target)); - } - - @Test - public void testChannelWithLoadBalancer() { - String policy = "round-robin"; - GrpcChannelDescriptor cfg = GrpcChannelDescriptor.builder() - .loadBalancerPolicy(policy) - .build(); - assertThat(cfg.loadBalancerPolicy().isPresent(), is(true)); - assertThat(cfg.loadBalancerPolicy().get(), is(policy)); - } - - @Test - public void testConfigLoading() { - String[] expectedChannelConfigNames = new String[] { - DEFAULT_HOST_PORT_CFG, DEFAULT_HOST_CFG, DEFAULT_PORT_CFG, - DEFAULT_HOST_SSL_ONE_WAY_CFG, DEFAULT_PORT_SSL_CFG, - DEFAULT_HOST_PORT_SSL_DISABLED_CFG - }; - - assertThat(grpcConfig.channels().size(), equalTo(expectedChannelConfigNames.length + 2)); - assertThat(grpcConfig.channels().keySet(), hasItems(expectedChannelConfigNames)); - assertThat(grpcConfig.channels().keySet(), hasItems(GrpcChannelsProvider.DEFAULT_CHANNEL_NAME)); - } - - @Test - public void testDefaultHostPortConfig() { - GrpcChannelDescriptor chCfg = grpcConfig.channels().get(DEFAULT_HOST_PORT_CFG); - assertThat(chCfg.host(), equalTo("localhost")); - assertThat(chCfg.port(), equalTo(1408)); - assertThat(chCfg.tlsDescriptor().isPresent(), is(false)); - assertThat(chCfg.target().isPresent(), is(false)); - assertThat(chCfg.loadBalancerPolicy().isPresent(), is(false)); - assertThat(chCfg.nameResolverFactory().isPresent(), is(false)); - } - - @Test - public void testDefaultHostConfig() { - GrpcChannelDescriptor chCfg = grpcConfig.channels().get(DEFAULT_HOST_CFG); - assertThat(chCfg.host(), equalTo("localhost")); - assertThat(chCfg.port(), equalTo(4096)); - assertThat(chCfg.tlsDescriptor().isPresent(), is(false)); - assertThat(chCfg.target().isPresent(), is(false)); - assertThat(chCfg.loadBalancerPolicy().isPresent(), is(false)); - assertThat(chCfg.nameResolverFactory().isPresent(), is(false)); - } - - @Test - public void testDefaultPortConfig() { - GrpcChannelDescriptor chCfg = grpcConfig.channels().get(DEFAULT_PORT_CFG); - assertThat(chCfg.host(), equalTo("non_default_host.com")); - assertThat(chCfg.port(), equalTo(1408)); - assertThat(chCfg.tlsDescriptor().isPresent(), is(false)); - assertThat(chCfg.target().isPresent(), is(false)); - assertThat(chCfg.loadBalancerPolicy().isPresent(), is(false)); - assertThat(chCfg.nameResolverFactory().isPresent(), is(false)); - } - - @Test - public void testDefaultHostPortSslDisabledConfig() { - GrpcChannelDescriptor chCfg = grpcConfig.channels().get(DEFAULT_HOST_PORT_SSL_DISABLED_CFG); - assertThat(chCfg.host(), equalTo("localhost")); - assertThat(chCfg.port(), equalTo(1408)); - - Optional descriptor = chCfg.tlsDescriptor(); - assertThat(descriptor.isPresent(), is(false)); - } - - @Test - public void testDefaultHostSslOneWay() { - GrpcChannelDescriptor chCfg = grpcConfig.channels().get(DEFAULT_HOST_SSL_ONE_WAY_CFG); - assertThat(chCfg.host(), equalTo("localhost")); - assertThat(chCfg.port(), equalTo(4096)); - - Resource trustResource = Resource.create(CA_CERT); - - Optional descriptor = chCfg.tlsDescriptor(); - assertThat(descriptor.isPresent(), is(true)); - GrpcTlsDescriptor ssl = descriptor.get(); - assertThat(ssl, notNullValue()); - assertThat(ssl.isEnabled(), equalTo(true)); - assertThat(ssl.tlsKey(), nullValue()); - assertThat(ssl.tlsCert(), nullValue()); - assertThat(ssl.tlsCaCert(), is(notNullValue())); - assertThat(ssl.tlsCaCert().location(), endsWith(trustResource.location())); - } - - @Test - public void testDefaultPortSsl() { - GrpcChannelDescriptor chCfg = grpcConfig.channels().get(DEFAULT_PORT_SSL_CFG); - assertThat(chCfg.host(), equalTo("non_default_host.com")); - assertThat(chCfg.port(), equalTo(1408)); - - Resource keyResource = Resource.create(CLIENT_KEY); - Resource certResource = Resource.create(CLIENT_CERT); - Resource trustResource = Resource.create(CA_CERT); - - Optional descriptor = chCfg.tlsDescriptor(); - assertThat(descriptor.isPresent(), is(true)); - GrpcTlsDescriptor ssl = descriptor.get(); - assertThat(ssl, notNullValue()); - assertThat(ssl.isEnabled(), equalTo(true)); - assertThat(ssl.tlsKey(), is(notNullValue())); - assertThat(ssl.tlsKey().location(), is(keyResource.location())); - assertThat(ssl.tlsCert(), is(notNullValue())); - assertThat(ssl.tlsCert().location(), endsWith(certResource.location())); - assertThat(ssl.tlsCaCert(), is(notNullValue())); - assertThat(ssl.tlsCaCert().location(), endsWith(trustResource.location())); - } -} diff --git a/microprofile/grpc/client/src/test/resources/application.yaml b/microprofile/grpc/client/src/test/resources/application.yaml index 00b3aef2e03..bf73807e8ae 100644 --- a/microprofile/grpc/client/src/test/resources/application.yaml +++ b/microprofile/grpc/client/src/test/resources/application.yaml @@ -28,3 +28,20 @@ server: passphrase: "password" resource: resource-path: "server.p12" + +grpc: + channels: + echo-channel: + port: 0 + tls: + trust: + keystore: + passphrase: "password" + trust-store: true + resource: + resource-path: "client.p12" + private-key: + keystore: + passphrase: "password" + resource: + resource-path: "client.p12" \ No newline at end of file diff --git a/microprofile/grpc/client/src/test/resources/logging.properties b/microprofile/grpc/client/src/test/resources/logging.properties index 7d166475b2b..1102463530f 100644 --- a/microprofile/grpc/client/src/test/resources/logging.properties +++ b/microprofile/grpc/client/src/test/resources/logging.properties @@ -31,4 +31,3 @@ java.util.logging.SimpleFormatter.format=%1$tY.%1$tm.%1$td %1$tH:%1$tM:%1$tS %4$ #io.helidon.config.level=INFO #io.helidon.security.level=INFO #io.helidon.common.level=INFO -#io.netty.level=INFO diff --git a/microprofile/grpc/client/src/test/resources/ssl/ca.pem b/microprofile/grpc/client/src/test/resources/ssl/ca.pem deleted file mode 100644 index 9edce3cf46e..00000000000 --- a/microprofile/grpc/client/src/test/resources/ssl/ca.pem +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICpjCCAY4CCQDsAfroMCH4tDANBgkqhkiG9w0BAQsFADAUMRIwEAYDVQQDDAls -b2NhbGhvc3QwIBcNMjAwMzMwMDk1NjU3WhgPMjI5NDAxMTIwOTU2NTdaMBQxEjAQ -BgNVBAMMCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB -AKbUgPWd5YM775bazo8MmuMHmYsSacUx+01NKVjbXPz8QHJULfdrYzJEs3yJ2bpP -mOBrXDTmW2+v1TUdSRjytf9b6/+NWixovGwhGF/iXJ9dhMhwp1AwL8PViuuJPTcf -acoAbFn1yJtNjZgalevyyN+eto+UFW+qJ+jn7ncTdReke3DeHiEA+lmk1DlAsGLR -sB2gQBC2Xb8wcCltivb/WJRJG+sHja2BTIUbywmYO9UtuLsLE/Wptl+t8ybObj2G -eE/t7/aM6KTOtXb6Q/Z7YPYSrVtIa/MwkFssmcVG0ldaAszUpq5bLanH5H3AHPN5 -1atNHVIYlwom2SrRazg5IisCAwEAATANBgkqhkiG9w0BAQsFAAOCAQEAWnMcVDGq -NxigGhtSFdmbnauLPd47ZEFh6iL+bG7QkT15XtpR5Q4GkxaIb1fTsqaxfj6WUG6Z -n6f9OHSuFGiQbV+h2zNVR4q+i7DcDFkbFrK0XtyUYkdHOot+I7XzURsocnZhWoKO -g+Yi0z4uBSol4olK4KNQLS39ePPrm76CqLf4i8wSUF5YEi0ExWhFgM4+19JvVyQ7 -tqRM1rAWajWp696fKP47ZV2Qn39+BRh8TYKIEdStaWWUxtycC8qhnkXspIG7etcN -3kju90KNuLky6WhNOm84GVZ4w339QTSk65yzUgxTxqJMK6elqgCESTuyGS1EJV00 -t2Dcg5m1p2llRQ== ------END CERTIFICATE----- diff --git a/microprofile/grpc/client/src/test/resources/ssl/clientCert.pem b/microprofile/grpc/client/src/test/resources/ssl/clientCert.pem deleted file mode 100644 index 49aaa60c6b5..00000000000 --- a/microprofile/grpc/client/src/test/resources/ssl/clientCert.pem +++ /dev/null @@ -1,16 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICmTCCAYECAQEwDQYJKoZIhvcNAQEFBQAwFDESMBAGA1UEAwwJbG9jYWxob3N0 -MCAXDTIwMDMzMDA5NTY1N1oYDzIyOTQwMTEyMDk1NjU3WjAPMQ0wCwYDVQQDDAR0 -ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxcZyW23ksgNBBo2P -f4VZxHLj+j6jWVVC5B4Wh3dl9VdSLII3T4uWQbNCoe9vIKZRhsuXn/fbHkd89MFi -GkC02kI+d0RpWULqgnRijbEu5fCsxBYa7dpI0DHkHWjTT2qk2vAw1h+z79orRiVt -wLy4vD4Ig6sbna/1AyK89FRHeq/YSMT3b0jhcxRxWSXmKb81UJ1HjNXIW8bElRcj -Z0vMNQsFWkOWOfyN31NRkM+sqy42fKsMPysitpUz5UQzVxpkm0rom89vDO1VubQl -zGK1gBV3Ll9kkZt5+UjkW/XE9leyRg1iSsY8l5NTp0RJNqpzZkrrPYHFIFhszLNe -NvtB4QIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQBv5M6wwOroq1iCz1wyWu/RxSGS -nGn4MdFEeIKTx9urMqTiHp9bW7gVGLHQ96ApxFF30PZ58X1JrJn+eerBaaI7yOo0 -FmVDlacqh5jSDvBoIzC8gFIfcDT/Q1xXmeB0KcgMdoZOhdkrX59qVenxrnihtd2I -uIWhutQB9T6VrTGiCB09gWkULsjHvKMJ1ucSG0a2K18Aqccypd3twXmllwPa/vrt -Kv7s9ZVvYibW7xXJBCV1kiZtx5TV+VO100/Ze94vvnAs7kCLZ16oGOFSj0JpCEFz -CAVAif0/huKd4bpMzwCosCPiKSGLETc6S+WTzoy0FAFmygZHEL9diXriQrMa ------END CERTIFICATE----- diff --git a/microprofile/grpc/client/src/test/resources/ssl/clientKey.pem b/microprofile/grpc/client/src/test/resources/ssl/clientKey.pem deleted file mode 100644 index b911b963790..00000000000 --- a/microprofile/grpc/client/src/test/resources/ssl/clientKey.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDFxnJbbeSyA0EG -jY9/hVnEcuP6PqNZVULkHhaHd2X1V1IsgjdPi5ZBs0Kh728gplGGy5ef99seR3z0 -wWIaQLTaQj53RGlZQuqCdGKNsS7l8KzEFhrt2kjQMeQdaNNPaqTa8DDWH7Pv2itG -JW3AvLi8PgiDqxudr/UDIrz0VEd6r9hIxPdvSOFzFHFZJeYpvzVQnUeM1chbxsSV -FyNnS8w1CwVaQ5Y5/I3fU1GQz6yrLjZ8qww/KyK2lTPlRDNXGmSbSuibz28M7VW5 -tCXMYrWAFXcuX2SRm3n5SORb9cT2V7JGDWJKxjyXk1OnREk2qnNmSus9gcUgWGzM -s142+0HhAgMBAAECggEAeZXwg+jhada6SS8KAxmWAEGpihSsE6VpBBjDPPDYS6Yt -LJO5MTvdWfK8ihVKukXFZRsQ0hVsLgdA+K9SglU5WdzTzjrOkUOkLCMk23sMG+yE -KeB1GbjSfrvNQ49IKVCknLyBKYI/+rqjU/J6sLzUzVVNorS0u5KLDCx1Abg2YWNW -6PmVdXQzusZB4NMD1eJOqxK4V0rFtFPkA+MgM74DKcMLz1uPnqZ2335Do6arwppv -Cffk63lLPbfaHu6dC7wmVZFSluQ8Ic+l+k+nwGvPFdbXTgnp+lUcTFBExZzh4vDC -yHW1IhCRb30bSd5VlQzv/5UtBXKjBEFXveHyrBZ6AQKBgQD9tu4G9D6SyNLKB5HI -95EvGkLck/mahGHkiXtLUiDeCBw3KIoHJL7MxpyO3n0yj9WIJV4lcc7kewKcz1SM -uHcVwbCauseD8XzOvulOQy3Sr7E9cuAoGF6Ep9+hUh6xSdClblej1/1yVLbXhW2O -9KTyGiHDzGiJ5baT7P2pQ0ci0QKBgQDHjoUMEBSOFXXKMeRl7h2Tp6KQbBACFMnP -xJpHysMDK5wheqJFmtAm5kgoIZ2fUfAsfU2/Uqbb8ZFYiFck1P6dFNlY0bMzhC3g -Nu2l/MzWTIw/fwZ15hy6JCEjSEAskdzA+AkfcvBQkf1eL64XX1KSVd/z8g9nvTDJ -CDY0jStSEQKBgQCyMWG6Fp9AHrYVWP2mRWJ9z5b4LyHWyXWruneS7irRZqbSgrF2 -1PMBBdl9anxKH8VcaspVyDoENPUfx2pdr01MRY5RDjAE1n3PAzz/T6WGXQlB3EXd -Q0hXKUSim/eckvhsyDPbil6ihycn9bl99wtGUt42E4G0oFb8TC3YTL1QkQKBgQCe -3sDfZKHop/8ZlPTfjV1wouHSFqX78i7kwQGOrEbq7DolkStFPMYAYg8KHBEPuLz7 -vlo6OgPrUHtFP24ZPZTi26lZg8El/1JCkZhLMGKnLVPubSNok2VFb+QN4cRtd0aH -PjCNIAVgL4nGBTGVG+dx5vofjRNkpIMFWQtGdSkK8QKBgQCm087/S1bbm4lZv/sP -HB26w9+gSpyFImU7ZWbsfYHtqbTCYdSru/5nGBHwDjz0uMDDuUo+sL6Vt7bFAArX -jR/edzXbfQf7boXsbPTx07rXvYkCe/usQsXpXQnf5QYlR5njj0r6fRLPfxygRbNS -KSdweVzS2u7UrN/NxBqWRPJcSg== ------END PRIVATE KEY----- diff --git a/microprofile/grpc/client/src/test/resources/ssl/keys.sh b/microprofile/grpc/client/src/test/resources/ssl/keys.sh deleted file mode 100644 index 91f811a5e60..00000000000 --- a/microprofile/grpc/client/src/test/resources/ssl/keys.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/bash -# -# Copyright (c) 2020, 2024 Oracle and/or its affiliates. -# -# 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. -# - -# ------------------------------------------------------------------------ -# This file was used to generate the keys and certs used for SSL testing. -# ------------------------------------------------------------------------ - -# Generate CA key: -openssl genrsa -des3 -passout pass:1111 -out ca.key 2048 - -# Generate CA certificate: -openssl req -passin pass:1111 -new -x509 -days 99999 -key ca.key -out ca.pem -subj "/CN=localhost" - -# Generate server key: -openssl genpkey -out serverKey.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048 - -# Generate server signing request -openssl req -passin pass:1111 -new -key serverKey.pem -out server.csr -subj "/CN=localhost" - -# Self-signed server certificate: -openssl x509 -req -passin pass:1111 -days 99999 -in server.csr -CA ca.pem -CAkey ca.key -set_serial 01 -out serverCert.pem - -# Generate client key -openssl genpkey -out clientKey.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048 - -# Generate client signing request: -openssl req -passin pass:1111 -new -key clientKey.pem -out client.csr -subj "/CN=test" - -# Self-signed client certificate: -openssl x509 -passin pass:1111 -req -days 99999 -in client.csr -CA ca.pem -CAkey ca.key -set_serial 01 -out clientCert.pem - -rm ca.key -rm server.csr -rm rm client.csr - diff --git a/microprofile/grpc/client/src/test/resources/ssl/serverCert.pem b/microprofile/grpc/client/src/test/resources/ssl/serverCert.pem deleted file mode 100644 index 058c630aa48..00000000000 --- a/microprofile/grpc/client/src/test/resources/ssl/serverCert.pem +++ /dev/null @@ -1,17 +0,0 @@ ------BEGIN CERTIFICATE----- -MIICnjCCAYYCAQEwDQYJKoZIhvcNAQEFBQAwFDESMBAGA1UEAwwJbG9jYWxob3N0 -MCAXDTIwMDMzMDA5NTY1N1oYDzIyOTQwMTEyMDk1NjU3WjAUMRIwEAYDVQQDDAls -b2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDU09otBo1b -sNSakO9hzDe3D37mY6i0q0iG3bIhrWb9crvizpIjyOCYuQzmdHCn488c5mEwZUpB -A14J7OX1HwyQyiA+YtNKrhH6D6lSJyxigt/clmINbLTyTS0HRf2M18SnJLlMb20a -kUSuE9AevQsD/68PEbGJYwNkD8Z/mYsTm8kOXBliMG0EX4vzJy3m/ZywJ4CzISC+ -VGm30hlUosssmfgtqmYSkE+PlrMT9lpcDec7zshOyd2QnEJdJERCC3EzfUpPAffh -iepJrfPwbHBJuOyRH+d/WEQwPP9z+AofsVhIxmgrj943tVMWbLoYSLBWFNPcWFBw -NOAoSE4PRnilAgMBAAEwDQYJKoZIhvcNAQEFBQADggEBABpmJFcAZ25R7AG9aV1i -kcGGivTGRq9snt3cuZyRY1XvQCMhZFaWZ5/WiLf7MCIDWKaZmTIbM2cwVI5b9V36 -nvnYd6JjW3ndtYXM0nFDCM3G5+Mw5FAVYobsup6MFgTVpTsNc8doK+b44A9KzXzB -CWXFN4UWptHsJXvS0gaXATXiAqfUbbY4P83CIQuUy6rV1QF9+OFDjWHvIoWK8VNY -U1IvLwzkeA+WGfNl75sOChQe3kdObkG4vu9xq05rHy7P9urWZ3NJWsby1s9cG7Cl -RaLu5XpaPy2tjEZHSWe0F9A8I5H/p5CCyh8/nzBH7CILvMGDzsIbTJSZEUArT+gy -nXI= ------END CERTIFICATE----- diff --git a/microprofile/grpc/client/src/test/resources/ssl/serverKey.pem b/microprofile/grpc/client/src/test/resources/ssl/serverKey.pem deleted file mode 100644 index db5a5ab90f0..00000000000 --- a/microprofile/grpc/client/src/test/resources/ssl/serverKey.pem +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDU09otBo1bsNSa -kO9hzDe3D37mY6i0q0iG3bIhrWb9crvizpIjyOCYuQzmdHCn488c5mEwZUpBA14J -7OX1HwyQyiA+YtNKrhH6D6lSJyxigt/clmINbLTyTS0HRf2M18SnJLlMb20akUSu -E9AevQsD/68PEbGJYwNkD8Z/mYsTm8kOXBliMG0EX4vzJy3m/ZywJ4CzISC+VGm3 -0hlUosssmfgtqmYSkE+PlrMT9lpcDec7zshOyd2QnEJdJERCC3EzfUpPAffhiepJ -rfPwbHBJuOyRH+d/WEQwPP9z+AofsVhIxmgrj943tVMWbLoYSLBWFNPcWFBwNOAo -SE4PRnilAgMBAAECggEBAKgY6EMV4MKiCVpHzXsOJJdnGtD3uAFzI+a55f8piaX3 -YCUFCXJQL+0Qg/rlzzEcArMN14e1CRAOi9EFFqAjtPYLX6pGviJHGJXMluz3Wdw5 -CH2fHbUCvmx+vmj3RAthRMbLf7u6ao9IW9mudnxAzhmLcoZRcEtWNBBtUVfpO2rw -+DA/0+P3vxrJ3Ky/QHcf/us+zpkJqhRn1yYe+J8VsGZVXHhOInlx8m9XHVCj+IDL -StA1n5jdIP6LA/Uu5o7fkWapnG7miyR1cUBrGvh0MrT5TnKNynMK0ooFUx5HcEZJ -hfHxwXMnnTz44kMCDe1BJscN2ElHSaSsfCy6zw0p8qUCgYEA+ZIM1RZe/KtkL4XC -WWTrfjLk39Fh2RgQoferG/HkKe8bNpJkL1RMr7YLA2E6r8O+mxeU46eok1P9Ela4 -TQawXHv5SwnJTmzjEpnO4v1VMYf6+RGAuRvsgMYZZ1HfOV/7x1jRPQOSq4QVepkL -zl2ecIJIKQ43CzJhb/nl0QMO6V8CgYEA2k96P5qRqOm0pXTMPe6UjfonPs5ZY8KQ -YVT9dTAmQgbua13TsbfT7FytDRjtis+GDWOXmUd7r8qvRK1P8zoeZtuDw6S8dR2+ -k/Zf0szYcyjjQkIXmh6ceYwx+vpvbiO5uCYZTePE1fpzMgpkNHzQk+RVpPBnuye1 -X+Jir/fKqHsCgYEA2LjSeeyuWb5ABuCh790qfvGVPSNnVA2IzA31whOhbiTcPdyM -MWmEGoX8NFgnjWBvUeD9g2AhjKa/ukAiVYk8d2OVDWuXK4p0+b8lIIqbg6Kw978S -SC0OiJj+kHFRZlKKowbm1JQYtubBfDARR4iWwN7x6O0WMZvzbzjUMFf2iAMCgYBO -c2cr+iDEAZAAMVPAIb9SsgVuZXrsBZwazg7zEOV+rrz46lPLtpK6iqdJYJ7kViUH -JLXyyCRjjMOlO17Suhz4u4PDR6zNrW2yAER5HVHfOF9KjTOsF7oFV+MSHPL0MnRn -/5DyU5qFhqXk4qUV05CkxNYeGqI8OE3Oci0irTovhwKBgQDyh+03r96OXBoS5H3o -w18ujDZIU/xYdbZXUgBCfAzrjf6uIva046aDVXHqzMsSBm6kY7Xw9vRxJA7E7ckQ -LO7pbmhlriOBiU6fu7oTmvR+k/E9e9KcbbjoftRG48uGabcGcZffO6neZEz2FH2l -7ekffuQqdc/26IWzMZyIVpFG+w== ------END PRIVATE KEY----- diff --git a/microprofile/grpc/client/src/test/resources/test-client-config.yaml b/microprofile/grpc/client/src/test/resources/test-client-config.yaml deleted file mode 100644 index 3ef2cbbd956..00000000000 --- a/microprofile/grpc/client/src/test/resources/test-client-config.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# -# Copyright (c) 2019, 2024 Oracle and/or its affiliates. -# -# 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. -# - -grpc: - channels: - default_host_port: - default_host: - port: 4096 - default_port: - host: "non_default_host.com" - default_host_port_ssl_disabled: - tls: - enabled: false - tls-key.resource: - resource-path: "ssl/clientKey.pem" - tls-cert.resource: - resource-path: "ssl/clientCert.pem" - tls-ca-cert.resource: - resource-path: "ssl/ca.pem" - default_host_ssl_one_way: - port: 4096 - tls: - enabled: true - tls-ca-cert.resource: - resource-path: "ssl/ca.pem" - default_port_ssl: - host: "non_default_host.com" - tls: - tls-key.resource: - resource-path: "ssl/clientKey.pem" - tls-cert.resource: - resource-path: "ssl/clientCert.pem" - tls-ca-cert.resource: - resource-path: "ssl/ca.pem" - with_target: - target: "dns://localhost:1408" - load-balancer-policy: "round-robin" \ No newline at end of file