diff --git a/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/GrpcServerProcessor.java b/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/GrpcServerProcessor.java index e216ad7fa2bf9..51a9134894710 100644 --- a/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/GrpcServerProcessor.java +++ b/extensions/grpc/deployment/src/main/java/io/quarkus/grpc/deployment/GrpcServerProcessor.java @@ -497,9 +497,15 @@ private void validateBindableService(BeanInfo bean, Type generatedBeanType, @BuildStep(onlyIf = IsNormal.class) KubernetesPortBuildItem registerGrpcServiceInKubernetes(List bindables) { if (!bindables.isEmpty()) { - int port = ConfigProvider.getConfig().getOptionalValue("quarkus.grpc.server.port", Integer.class) - .orElse(9000); - return new KubernetesPortBuildItem(port, "grpc"); + boolean useSeparateServer = ConfigProvider.getConfig().getOptionalValue("quarkus.grpc.server.use-separate-server", + Boolean.class) + .orElse(true); + if (useSeparateServer) { + // Only expose the named port "grpc" if the gRPC server is exposed using a separate server. + int port = ConfigProvider.getConfig().getOptionalValue("quarkus.grpc.server.port", Integer.class) + .orElse(9000); + return new KubernetesPortBuildItem(port, "grpc"); + } } return null; } diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/invoker.properties b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/invoker.properties new file mode 100644 index 0000000000000..bdba9223dc230 --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/invoker.properties @@ -0,0 +1 @@ +invoker.goals=clean package \ No newline at end of file diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/pom.xml b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/pom.xml new file mode 100644 index 0000000000000..a6ff4b00cccdf --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/pom.xml @@ -0,0 +1,121 @@ + + + 4.0.0 + org.acme + kubernetes-with-grpc-same-server + 0.1-SNAPSHOT + + UTF-8 + 3.0.0 + 11 + UTF-8 + 11 + + + + + io.quarkus + quarkus-bom + @project.version@ + pom + import + + + + + + io.quarkus + quarkus-grpc + + + io.quarkus + quarkus-resteasy-reactive + + + io.quarkus + quarkus-kubernetes + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + + + + io.quarkus + quarkus-maven-plugin + @project.version@ + + + + build + generate-code + generate-code-tests + + + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + native + + + native + + + + native + + + + + org.apache.maven.plugins + maven-surefire-plugin + + ${native.surefire.skip} + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + + diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/src/main/java/org/acme/GrpcHelloService.java b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/src/main/java/org/acme/GrpcHelloService.java new file mode 100644 index 0000000000000..a11c0b8ce4016 --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/src/main/java/org/acme/GrpcHelloService.java @@ -0,0 +1,15 @@ +package org.acme; + +import io.grpc.stub.StreamObserver; + +@io.quarkus.grpc.GrpcService +public class GrpcHelloService extends GreeterGrpc.GreeterImplBase { + + @Override + public void sayHello(HelloRequest request, StreamObserver responseObserver) { + String name = request.getName(); + String message = "Hello " + name; + responseObserver.onNext(HelloReply.newBuilder().setMessage(message).build()); + responseObserver.onCompleted(); + } +} diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/src/main/java/org/acme/Hello.java b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/src/main/java/org/acme/Hello.java new file mode 100644 index 0000000000000..95b11f63bda44 --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/src/main/java/org/acme/Hello.java @@ -0,0 +1,16 @@ +package org.acme; + +import jakarta.ws.rs.GET; +import jakarta.ws.rs.Path; +import jakarta.ws.rs.Produces; +import jakarta.ws.rs.core.MediaType; + +@Path("/hello") +public class Hello { + + @GET + @Produces(MediaType.TEXT_PLAIN) + public String hello() { + return "hello"; + } +} diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/src/main/proto/helloworld.proto b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/src/main/proto/helloworld.proto new file mode 100644 index 0000000000000..9c18544d9068d --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/src/main/proto/helloworld.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_outer_classname = "HelloWorldProto"; + +package org.acme; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} \ No newline at end of file diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/src/main/resources/application.properties b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/src/main/resources/application.properties new file mode 100644 index 0000000000000..377932d21a9cf --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/src/main/resources/application.properties @@ -0,0 +1 @@ +quarkus.grpc.server.use-separate-server=false \ No newline at end of file diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/verify.groovy b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/verify.groovy new file mode 100644 index 0000000000000..c653ab952ba1c --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc-same-server/verify.groovy @@ -0,0 +1,34 @@ +import io.dekorate.utils.Serialization +import io.fabric8.kubernetes.api.model.ContainerPort +import io.fabric8.kubernetes.api.model.KubernetesList +import io.fabric8.kubernetes.api.model.Service +import io.fabric8.kubernetes.api.model.ServicePort +import io.fabric8.kubernetes.api.model.apps.Deployment; + +//Check that file exits +String base = basedir +File kubernetesYml = new File(base, "target/kubernetes/kubernetes.yml") +assert kubernetesYml.exists() +kubernetesYml.withInputStream { stream -> + //Check that its parse-able + KubernetesList list = Serialization.unmarshalAsList(stream) + assert list != null + + Deployment deployment = list.items.find{r -> r.kind == "Deployment"} + + //Check that ti contains the Deployment with the expected ports + assert deployment != null + assert deployment.metadata.name == "kubernetes-with-grpc-same-server" + List containerPorts = deployment.spec.template.spec.containers.get(0).ports + assert containerPorts.stream().anyMatch(p -> p.getName() == "http" && p.containerPort == 8080); + assert containerPorts.stream().noneMatch(p -> p.getName() == "grpc"); + + Service service = list.items.find{ r -> r.kind == "Service"} + + //Check that ti contains the Service with the expected ports + assert service != null + assert service.metadata.name == "kubernetes-with-grpc-same-server" + List servicePorts = service.spec.ports + assert servicePorts.stream().anyMatch(p -> p.getName() == "http" && p.targetPort.intVal == 8080); + assert servicePorts.stream().noneMatch(p -> p.getName() == "grpc"); +} diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/invoker.properties b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/invoker.properties new file mode 100644 index 0000000000000..bdba9223dc230 --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/invoker.properties @@ -0,0 +1 @@ +invoker.goals=clean package \ No newline at end of file diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/pom.xml b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/pom.xml new file mode 100644 index 0000000000000..e05f5fbd3fc26 --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/pom.xml @@ -0,0 +1,117 @@ + + + 4.0.0 + org.acme + kubernetes-with-grpc + 0.1-SNAPSHOT + + UTF-8 + 3.0.0 + 11 + UTF-8 + 11 + + + + + io.quarkus + quarkus-bom + @project.version@ + pom + import + + + + + + io.quarkus + quarkus-grpc + + + io.quarkus + quarkus-kubernetes + + + io.quarkus + quarkus-junit5 + test + + + io.rest-assured + rest-assured + test + + + + + + io.quarkus + quarkus-maven-plugin + @project.version@ + + + + build + generate-code + generate-code-tests + + + + + + maven-surefire-plugin + ${surefire-plugin.version} + + + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + native + + + native + + + + native + + + + + org.apache.maven.plugins + maven-surefire-plugin + + ${native.surefire.skip} + + + + maven-failsafe-plugin + ${surefire-plugin.version} + + + + integration-test + verify + + + + ${project.build.directory}/${project.build.finalName}-runner + org.jboss.logmanager.LogManager + ${maven.home} + + + + + + + + + + diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/src/main/java/org/acme/GrpcHelloService.java b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/src/main/java/org/acme/GrpcHelloService.java new file mode 100644 index 0000000000000..a11c0b8ce4016 --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/src/main/java/org/acme/GrpcHelloService.java @@ -0,0 +1,15 @@ +package org.acme; + +import io.grpc.stub.StreamObserver; + +@io.quarkus.grpc.GrpcService +public class GrpcHelloService extends GreeterGrpc.GreeterImplBase { + + @Override + public void sayHello(HelloRequest request, StreamObserver responseObserver) { + String name = request.getName(); + String message = "Hello " + name; + responseObserver.onNext(HelloReply.newBuilder().setMessage(message).build()); + responseObserver.onCompleted(); + } +} diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/src/main/proto/helloworld.proto b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/src/main/proto/helloworld.proto new file mode 100644 index 0000000000000..9c18544d9068d --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/src/main/proto/helloworld.proto @@ -0,0 +1,22 @@ +syntax = "proto3"; + +option java_multiple_files = true; +option java_outer_classname = "HelloWorldProto"; + +package org.acme; + +// The greeting service definition. +service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} +} + +// The request message containing the user's name. +message HelloRequest { + string name = 1; +} + +// The response message containing the greetings +message HelloReply { + string message = 1; +} \ No newline at end of file diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/src/main/resources/application.properties b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/src/main/resources/application.properties new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/verify.groovy b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/verify.groovy new file mode 100644 index 0000000000000..1b143fd957b53 --- /dev/null +++ b/integration-tests/kubernetes/maven-invoker-way/src/it/kubernetes-with-grpc/verify.groovy @@ -0,0 +1,34 @@ +import io.dekorate.utils.Serialization +import io.fabric8.kubernetes.api.model.ContainerPort +import io.fabric8.kubernetes.api.model.KubernetesList +import io.fabric8.kubernetes.api.model.Service +import io.fabric8.kubernetes.api.model.ServicePort +import io.fabric8.kubernetes.api.model.apps.Deployment; + +//Check that file exits +String base = basedir +File kubernetesYml = new File(base, "target/kubernetes/kubernetes.yml") +assert kubernetesYml.exists() +kubernetesYml.withInputStream { stream -> + //Check that its parse-able + KubernetesList list = Serialization.unmarshalAsList(stream) + assert list != null + + Deployment deployment = list.items.find{r -> r.kind == "Deployment"} + + //Check that ti contains the Deployment with the expected ports + assert deployment != null + assert deployment.metadata.name == "kubernetes-with-grpc" + List containerPorts = deployment.spec.template.spec.containers.get(0).ports + assert containerPorts.stream().anyMatch(p -> p.getName() == "http" && p.containerPort == 8080); + assert containerPorts.stream().anyMatch(p -> p.getName() == "grpc" && p.containerPort == 9000); + + Service service = list.items.find{ r -> r.kind == "Service"} + + //Check that ti contains the Service with the expected ports + assert service != null + assert service.metadata.name == "kubernetes-with-grpc" + List servicePorts = service.spec.ports + assert servicePorts.stream().anyMatch(p -> p.getName() == "http" && p.targetPort.intVal == 8080); + assert servicePorts.stream().anyMatch(p -> p.getName() == "grpc" && p.targetPort.intVal == 9000); +}