From fb8ec0b6fd6816aab56b82db5d5662445985dc7e Mon Sep 17 00:00:00 2001 From: pablo gonzalez granados Date: Fri, 18 Mar 2022 16:33:45 +0100 Subject: [PATCH] Add Stork + k8s coverage - default service discovery - default load balncer --- README.md | 6 +- pom.xml | 2 +- .../io/quarkus/ts/stork/PongResource.java | 45 ------- .../src/main/resources/application.properties | 1 - .../OpenShiftStorkServiceDiscoveryIT.java | 80 ------------- .../src/test/resources/test.properties | 1 - .../{stork-consul => stork}/pom.xml | 2 +- .../quarkus/ts/stork/MyBackendPongProxy.java | 3 +- .../quarkus/ts/stork/MyBackendPungProxy.java | 0 .../io/quarkus/ts/stork/PingResource.java | 22 ++-- .../quarkus/ts/stork/PongReplicaResource.java | 24 ++-- .../io/quarkus/ts/stork/PongResource.java | 54 +++++++++ .../io/quarkus/ts/stork/PungResource.java | 0 .../src/main/resources/application.properties | 3 + .../OpenShiftStorkServiceDiscoveryIT.java | 111 ++++++++++++++++++ .../ts/stork/StorkServiceDiscoveryIT.java | 14 +-- .../src/test/resources/cluster-role.yaml | 2 +- .../src/test/resources/fabric8-rbac.yaml | 1 - .../stork/src/test/resources/test.properties | 2 + 19 files changed, 209 insertions(+), 164 deletions(-) delete mode 100644 service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/PongResource.java delete mode 100644 service-discovery/stork-consul/src/main/resources/application.properties delete mode 100644 service-discovery/stork-consul/src/test/java/io/quarkus/ts/stork/OpenShiftStorkServiceDiscoveryIT.java delete mode 100644 service-discovery/stork-consul/src/test/resources/test.properties rename service-discovery/{stork-consul => stork}/pom.xml (97%) rename service-discovery/{stork-consul => stork}/src/main/java/io/quarkus/ts/stork/MyBackendPongProxy.java (82%) rename service-discovery/{stork-consul => stork}/src/main/java/io/quarkus/ts/stork/MyBackendPungProxy.java (100%) rename service-discovery/{stork-consul => stork}/src/main/java/io/quarkus/ts/stork/PingResource.java (56%) rename service-discovery/{stork-consul => stork}/src/main/java/io/quarkus/ts/stork/PongReplicaResource.java (58%) create mode 100644 service-discovery/stork/src/main/java/io/quarkus/ts/stork/PongResource.java rename service-discovery/{stork-consul => stork}/src/main/java/io/quarkus/ts/stork/PungResource.java (100%) create mode 100644 service-discovery/stork/src/main/resources/application.properties create mode 100644 service-discovery/stork/src/test/java/io/quarkus/ts/stork/OpenShiftStorkServiceDiscoveryIT.java rename service-discovery/{stork-consul => stork}/src/test/java/io/quarkus/ts/stork/StorkServiceDiscoveryIT.java (95%) rename service-discovery/{stork-consul => stork}/src/test/resources/cluster-role.yaml (88%) rename service-discovery/{stork-consul => stork}/src/test/resources/fabric8-rbac.yaml (86%) create mode 100644 service-discovery/stork/src/test/resources/test.properties diff --git a/README.md b/README.md index b4053c251..e47b11559 100644 --- a/README.md +++ b/README.md @@ -651,9 +651,9 @@ this.router.get("/secured") * authZ::authorize: custom AuthZ(authorization) provider. * secure.helloWorld(rc): actual http endpoint (Rest layer). -### Service-discovery/stork-consul +### Service-discovery/stork -Verifies Stork-consul integration in order to provide service discovering and round-robin load balancing between services +Verifies Stork integration in order to provide service discovering and round-robin load balancing between services `StorkServiceDiscoveryIT` scenario deploys four services: * Pung: is a simple endpoint that returns "pung" as a string @@ -662,8 +662,6 @@ Verifies Stork-consul integration in order to provide service discovering and ro * Ping: is the main client microservice that will use `pung` and `pong` (Pong and PongReplica) services. The service discovery will be done by Stork, and the request dispatching between "pong" services is going to be done by Stork load balancer. - - ### `monitoring/microprofile` Verifies combined usage of MicroProfile RestClient, Fault Tolerance and OpenTracing. diff --git a/pom.xml b/pom.xml index 0e8572830..36b8ee977 100644 --- a/pom.xml +++ b/pom.xml @@ -349,7 +349,7 @@ docker-build javaee-like-getting-started scaling - service-discovery/stork-consul + service-discovery/stork lifecycle-application external-applications scheduling/quartz diff --git a/service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/PongResource.java b/service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/PongResource.java deleted file mode 100644 index 30d052d73..000000000 --- a/service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/PongResource.java +++ /dev/null @@ -1,45 +0,0 @@ -package io.quarkus.ts.stork; - -import javax.enterprise.event.Observes; -import javax.ws.rs.core.MediaType; - -import org.eclipse.microprofile.config.inject.ConfigProperty; - -import io.quarkus.runtime.StartupEvent; -import io.quarkus.vertx.web.Route; -import io.quarkus.vertx.web.RouteBase; -import io.smallrye.mutiny.Uni; -import io.vertx.ext.consul.ConsulClientOptions; -import io.vertx.ext.consul.ServiceOptions; -import io.vertx.mutiny.core.Vertx; -import io.vertx.mutiny.ext.consul.ConsulClient; - -@RouteBase(path = "/pong", produces = MediaType.TEXT_PLAIN) -public class PongResource { - - public static final String PONG_SERVICE_NAME = "pong"; - private static final String DEFAULT_PONG_RESPONSE = "pong"; - - @ConfigProperty(name = "stork.pong.service-discovery.consul-host") - String host; - @ConfigProperty(name = "stork.pong.service-discovery.consul-port") - String port; - @ConfigProperty(name = "pong-service-port") - String pongPort; - @ConfigProperty(name = "pong-service-host") - String pongHost; - - public void init(@Observes StartupEvent ev, Vertx vertx) { - ConsulClient client = ConsulClient.create(vertx, - new ConsulClientOptions().setHost(host).setPort(Integer.parseInt(port))); - - client.registerServiceAndAwait( - new ServiceOptions().setPort(Integer.parseInt(pongPort)).setAddress(pongHost).setName(PONG_SERVICE_NAME) - .setId("pong")); - } - - @Route(path = "/", methods = Route.HttpMethod.GET) - public Uni pong() { - return Uni.createFrom().item(DEFAULT_PONG_RESPONSE); - } -} diff --git a/service-discovery/stork-consul/src/main/resources/application.properties b/service-discovery/stork-consul/src/main/resources/application.properties deleted file mode 100644 index 9e4640c38..000000000 --- a/service-discovery/stork-consul/src/main/resources/application.properties +++ /dev/null @@ -1 +0,0 @@ -# application properties should be here diff --git a/service-discovery/stork-consul/src/test/java/io/quarkus/ts/stork/OpenShiftStorkServiceDiscoveryIT.java b/service-discovery/stork-consul/src/test/java/io/quarkus/ts/stork/OpenShiftStorkServiceDiscoveryIT.java deleted file mode 100644 index f14c11b50..000000000 --- a/service-discovery/stork-consul/src/test/java/io/quarkus/ts/stork/OpenShiftStorkServiceDiscoveryIT.java +++ /dev/null @@ -1,80 +0,0 @@ -package io.quarkus.ts.stork; - -import static java.util.regex.Pattern.quote; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.is; - -import java.io.File; -import java.nio.file.Path; -import java.nio.file.Paths; - -import javax.inject.Inject; - -import org.apache.http.HttpStatus; -import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.Order; -import org.junit.jupiter.api.Test; - -import io.quarkus.test.bootstrap.RestService; -import io.quarkus.test.bootstrap.inject.OpenShiftClient; -import io.quarkus.test.scenarios.OpenShiftScenario; -import io.quarkus.test.services.QuarkusApplication; -import io.quarkus.test.utils.FileUtils; - -@OpenShiftScenario -public class OpenShiftStorkServiceDiscoveryIT { - - private static final String PREFIX = "ping-"; - private static final String CLUSTER_ROLE_FILE_NAME = "cluster-role.yaml"; - private static final String RBAC_FILE_NAME = "fabric8-rbac.yaml"; - - @Inject - static OpenShiftClient openshift; - - @QuarkusApplication(classes = PungResource.class) - static RestService pung = new RestService() - .withProperty("stork.pung.service-discovery", "kubernetes") - .withProperty("stork.pung.service-discovery.k8s-namespace", "all"); - - @QuarkusApplication(classes = { PingResource.class, MyBackendPungProxy.class, MyBackendPongProxy.class }) - static RestService ping = new RestService().onPreStart(app -> setupClusterRoles()) - .withProperty("stork.pung.service-discovery", "kubernetes") - .withProperty("stork.pung.service-discovery.k8s-namespace", "all"); - - @AfterAll - public static void tearDown() { - openshift.delete(Paths.get(new File("target/test-classes/" + CLUSTER_ROLE_FILE_NAME).toURI())); - openshift.delete(Paths.get(new File("target/test-classes/" + RBAC_FILE_NAME).toURI())); - } - - @Test - public void invokeServiceByName() { - String response = makePingCall("pung"); - assertThat("Service discovery by name fail.", PREFIX + "pung", is(response)); - } - - @Test - public void storkLoadBalancerByRoundRobin() { - - } - - private String makePingCall(String subPath) { - return ping - .given() - .get("/ping/" + subPath).then() - .statusCode(HttpStatus.SC_OK) - .extract().body().asString(); - } - - /** - * setup `stork-service-discovery-kubernetes` - roles and roles bindings (required) - */ - private static void setupClusterRoles() { - String namespace = openshift.project(); - openshift.apply(Paths.get(new File("target/test-classes/" + CLUSTER_ROLE_FILE_NAME).toURI())); - String content = FileUtils.loadFile(new File("target/test-classes/" + RBAC_FILE_NAME)) - .replaceAll(quote("${NAMESPACE}"), namespace); - Path target = FileUtils.copyContentTo(content, new File("target/test-classes/" + RBAC_FILE_NAME).toPath()); - openshift.apply(target); - } -} \ No newline at end of file diff --git a/service-discovery/stork-consul/src/test/resources/test.properties b/service-discovery/stork-consul/src/test/resources/test.properties deleted file mode 100644 index 87eca67da..000000000 --- a/service-discovery/stork-consul/src/test/resources/test.properties +++ /dev/null @@ -1 +0,0 @@ -ts.pung.openshift.use-internal-service-as-url=true \ No newline at end of file diff --git a/service-discovery/stork-consul/pom.xml b/service-discovery/stork/pom.xml similarity index 97% rename from service-discovery/stork-consul/pom.xml rename to service-discovery/stork/pom.xml index 75db3664d..729075597 100644 --- a/service-discovery/stork-consul/pom.xml +++ b/service-discovery/stork/pom.xml @@ -9,7 +9,7 @@ stork jar - Quarkus QE TS: Service-discovery: Stork-consul + Quarkus QE TS: Service-discovery: Stork io.smallrye.stork diff --git a/service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/MyBackendPongProxy.java b/service-discovery/stork/src/main/java/io/quarkus/ts/stork/MyBackendPongProxy.java similarity index 82% rename from service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/MyBackendPongProxy.java rename to service-discovery/stork/src/main/java/io/quarkus/ts/stork/MyBackendPongProxy.java index b54d474b7..e222e6518 100644 --- a/service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/MyBackendPongProxy.java +++ b/service-discovery/stork/src/main/java/io/quarkus/ts/stork/MyBackendPongProxy.java @@ -6,6 +6,7 @@ import javax.ws.rs.core.MediaType; import org.eclipse.microprofile.rest.client.inject.RegisterRestClient; +import org.jboss.resteasy.reactive.RestResponse; import io.smallrye.mutiny.Uni; @@ -15,5 +16,5 @@ public interface MyBackendPongProxy { @GET @Produces(MediaType.TEXT_PLAIN) @Path("/") - Uni get(); + Uni> get(); } diff --git a/service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/MyBackendPungProxy.java b/service-discovery/stork/src/main/java/io/quarkus/ts/stork/MyBackendPungProxy.java similarity index 100% rename from service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/MyBackendPungProxy.java rename to service-discovery/stork/src/main/java/io/quarkus/ts/stork/MyBackendPungProxy.java diff --git a/service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/PingResource.java b/service-discovery/stork/src/main/java/io/quarkus/ts/stork/PingResource.java similarity index 56% rename from service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/PingResource.java rename to service-discovery/stork/src/main/java/io/quarkus/ts/stork/PingResource.java index 6ce0dd36d..4c6c0e35b 100644 --- a/service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/PingResource.java +++ b/service-discovery/stork/src/main/java/io/quarkus/ts/stork/PingResource.java @@ -13,6 +13,9 @@ @RouteBase(path = "/ping", produces = MediaType.TEXT_PLAIN) public class PingResource { + public static final String PING_PREFIX = "ping-"; + public static final String HEADER_ID = "x-id"; + @RestClient MyBackendPongProxy pongService; @@ -20,18 +23,17 @@ public class PingResource { MyBackendPungProxy pungService; @Route(methods = Route.HttpMethod.GET, path = "/pung") - public Uni pung(RoutingContext context) { - return formatResponse(pungService.get()); + public Uni pung() { + return pungService.get() + .onFailure().transform(error -> new WebApplicationException(error.getMessage())) + .map(resp -> PING_PREFIX + resp); } @Route(methods = Route.HttpMethod.GET, path = "/pong") - public Uni pong(RoutingContext context) { - return formatResponse(pongService.get()); - } - - private Uni formatResponse(Uni response) { - return response - .onFailure().transform(error -> new WebApplicationException(error.getMessage())) - .map(resp -> "ping-" + resp); + public void pong(RoutingContext context) { + pongService.get().onFailure().transform(error -> new WebApplicationException(error.getMessage())).subscribe() + .with(resp -> context.response() + .putHeader(HEADER_ID, resp.getHeaderString(HEADER_ID)) + .end(PING_PREFIX + resp.getEntity())); } } diff --git a/service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/PongReplicaResource.java b/service-discovery/stork/src/main/java/io/quarkus/ts/stork/PongReplicaResource.java similarity index 58% rename from service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/PongReplicaResource.java rename to service-discovery/stork/src/main/java/io/quarkus/ts/stork/PongReplicaResource.java index 12860dc2f..9b7fa91d0 100644 --- a/service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/PongReplicaResource.java +++ b/service-discovery/stork/src/main/java/io/quarkus/ts/stork/PongReplicaResource.java @@ -21,22 +21,26 @@ public class PongReplicaResource { private static final String DEFAULT_PONG_REPLICA_RESPONSE = "pongReplica"; - @ConfigProperty(name = "stork.pong-replica.service-discovery.consul-host") + @ConfigProperty(name = "stork.pong-replica.service-discovery.consul-host", defaultValue = "localhost") String host; - @ConfigProperty(name = "stork.pong-replica.service-discovery.consul-port") + @ConfigProperty(name = "stork.pong-replica.service-discovery.consul-port", defaultValue = "8500") String port; - @ConfigProperty(name = "pong-replica-service-port") + @ConfigProperty(name = "pong-replica-service-port", defaultValue = "8080") String pongPort; - @ConfigProperty(name = "pong-replica-service-host") + @ConfigProperty(name = "pong-replica-service-host", defaultValue = "localhost") String pongHost; + @ConfigProperty(name = "stork.pong-replica.service-discovery", defaultValue = "consul") + String serviceDiscoveryType; public void init(@Observes StartupEvent ev, Vertx vertx) { - ConsulClient client = ConsulClient.create(vertx, - new ConsulClientOptions().setHost(host).setPort(Integer.parseInt(port))); - - client.registerServiceAndAwait( - new ServiceOptions().setPort(Integer.parseInt(pongPort)).setAddress(pongHost).setName(PONG_SERVICE_NAME) - .setId("pongReplica")); + if (serviceDiscoveryType.equalsIgnoreCase("consul")) { + ConsulClient client = ConsulClient.create(vertx, + new ConsulClientOptions().setHost(host).setPort(Integer.parseInt(port))); + + client.registerServiceAndAwait( + new ServiceOptions().setPort(Integer.parseInt(pongPort)).setAddress(pongHost).setName(PONG_SERVICE_NAME) + .setId("pongReplica")); + } } @Route(path = "/", methods = Route.HttpMethod.GET) diff --git a/service-discovery/stork/src/main/java/io/quarkus/ts/stork/PongResource.java b/service-discovery/stork/src/main/java/io/quarkus/ts/stork/PongResource.java new file mode 100644 index 000000000..67b6d6076 --- /dev/null +++ b/service-discovery/stork/src/main/java/io/quarkus/ts/stork/PongResource.java @@ -0,0 +1,54 @@ +package io.quarkus.ts.stork; + +import java.util.UUID; + +import javax.enterprise.event.Observes; +import javax.ws.rs.core.MediaType; + +import org.eclipse.microprofile.config.inject.ConfigProperty; + +import io.quarkus.runtime.StartupEvent; +import io.quarkus.vertx.web.Route; +import io.quarkus.vertx.web.RouteBase; +import io.vertx.ext.consul.ConsulClientOptions; +import io.vertx.ext.consul.ServiceOptions; +import io.vertx.ext.web.RoutingContext; +import io.vertx.mutiny.core.Vertx; +import io.vertx.mutiny.ext.consul.ConsulClient; + +@RouteBase(path = "/pong", produces = MediaType.TEXT_PLAIN) +public class PongResource { + + public static final String PONG_SERVICE_NAME = "pong"; + private static final String DEFAULT_PONG_RESPONSE = "pong"; + private static final String HEADER_ID = "x-id"; + private String instanceUniqueId; + + @ConfigProperty(name = "stork.pong.service-discovery.consul-host", defaultValue = "localhost") + String host; + @ConfigProperty(name = "stork.pong.service-discovery.consul-port", defaultValue = "8500") + String port; + @ConfigProperty(name = "pong-service-port", defaultValue = "8080") + String pongPort; + @ConfigProperty(name = "pong-service-host", defaultValue = "localhost") + String pongHost; + @ConfigProperty(name = "stork.pong.service-discovery", defaultValue = "consul") + String serviceDiscoveryType; + + public void init(@Observes StartupEvent ev, Vertx vertx) { + instanceUniqueId = UUID.randomUUID().toString(); + if (serviceDiscoveryType.equalsIgnoreCase("consul")) { + ConsulClient client = ConsulClient.create(vertx, + new ConsulClientOptions().setHost(host).setPort(Integer.parseInt(port))); + + client.registerServiceAndAwait( + new ServiceOptions().setPort(Integer.parseInt(pongPort)).setAddress(pongHost).setName(PONG_SERVICE_NAME) + .setId("pong")); + } + } + + @Route(path = "/", methods = Route.HttpMethod.GET) + public void pong(final RoutingContext context) { + context.response().putHeader(HEADER_ID, instanceUniqueId).end(DEFAULT_PONG_RESPONSE); + } +} diff --git a/service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/PungResource.java b/service-discovery/stork/src/main/java/io/quarkus/ts/stork/PungResource.java similarity index 100% rename from service-discovery/stork-consul/src/main/java/io/quarkus/ts/stork/PungResource.java rename to service-discovery/stork/src/main/java/io/quarkus/ts/stork/PungResource.java diff --git a/service-discovery/stork/src/main/resources/application.properties b/service-discovery/stork/src/main/resources/application.properties new file mode 100644 index 000000000..2a708270c --- /dev/null +++ b/service-discovery/stork/src/main/resources/application.properties @@ -0,0 +1,3 @@ +# application properties should be here +# TODO https://github.com/quarkusio/quarkus/issues/24444 +quarkus.native.additional-build-args=--allow-incomplete-classpath, --initialize-at-run-time=io.fabric8.kubernetes.client.internal.CertUtils, --enable-url-protocols=https diff --git a/service-discovery/stork/src/test/java/io/quarkus/ts/stork/OpenShiftStorkServiceDiscoveryIT.java b/service-discovery/stork/src/test/java/io/quarkus/ts/stork/OpenShiftStorkServiceDiscoveryIT.java new file mode 100644 index 000000000..a670edd72 --- /dev/null +++ b/service-discovery/stork/src/test/java/io/quarkus/ts/stork/OpenShiftStorkServiceDiscoveryIT.java @@ -0,0 +1,111 @@ +package io.quarkus.ts.stork; + +import static io.quarkus.ts.stork.PingResource.HEADER_ID; +import static io.quarkus.ts.stork.PingResource.PING_PREFIX; +import static java.util.regex.Pattern.quote; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.is; + +import java.io.File; +import java.nio.file.Paths; +import java.util.HashMap; +import java.util.Map; + +import javax.inject.Inject; + +import org.apache.http.HttpStatus; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import io.quarkus.test.bootstrap.RestService; +import io.quarkus.test.bootstrap.inject.OpenShiftClient; +import io.quarkus.test.scenarios.OpenShiftScenario; +import io.quarkus.test.services.QuarkusApplication; +import io.quarkus.test.utils.FileUtils; +import io.restassured.response.ValidatableResponse; + +@OpenShiftScenario +public class OpenShiftStorkServiceDiscoveryIT { + + private static final String CLUSTER_ROLE_FILE_NAME = "cluster-role.yaml"; + private static final String RBAC_FILE_NAME = "fabric8-rbac.yaml"; + private static final int PONG_INSTANCES_AMOUNT = 2; // we need at least two instances in order to verify stork LB + + @Inject + static OpenShiftClient openshift; + + @QuarkusApplication(classes = PungResource.class) + static RestService pung = new RestService() + .withProperty("stork.pung.service-discovery", "kubernetes") + .withProperty("stork.pung.service-discovery.k8s-namespace", "all"); + + @QuarkusApplication(classes = PongResource.class) + static RestService pong = new RestService() + .onPostStart(app -> openshift.scaleTo(app, PONG_INSTANCES_AMOUNT)) + .withProperty("stork.pong.service-discovery", "kubernetes") + .withProperty("stork.pong.service-discovery.k8s-namespace", "all"); + + @QuarkusApplication(classes = { PingResource.class, MyBackendPungProxy.class, MyBackendPongProxy.class }) + static RestService ping = new RestService().onPreStart(app -> setupClusterRoles()) + .withProperty("stork.pong.service-discovery", "kubernetes") + .withProperty("stork.pong.service-discovery.k8s-namespace", "all") + .withProperty("stork.pung.service-discovery", "kubernetes") + .withProperty("stork.pung.service-discovery.k8s-namespace", "all"); + + @AfterAll + public static void tearDown() { + openshift.delete(Paths.get(new File("target/test-classes/" + CLUSTER_ROLE_FILE_NAME).toURI())); + openshift.delete(Paths.get(new File("target/test-classes/" + RBAC_FILE_NAME).toURI())); + } + + @Test + public void invokeServiceByName() { + String response = makePingCall("pung").extract().body().asString(); + assertThat("Service discovery by name fail.", PING_PREFIX + "pung", is(response)); + } + + @Test + public void storkLoadBalancerByRoundRobin() { + Map uniqueResp = new HashMap<>(); + final int requestAmount = 10; + final int roundRobinError = (requestAmount / PONG_INSTANCES_AMOUNT) - 1; + for (int i = 0; i < requestAmount; i++) { + String pongInstanceId = makePingCall("pong").extract().header(HEADER_ID); + if (uniqueResp.containsKey(pongInstanceId)) { + uniqueResp.put(pongInstanceId, uniqueResp.get(pongInstanceId) + 1); + } else { + uniqueResp.put(pongInstanceId, 1); + } + } + + Assertions.assertEquals(uniqueResp.size(), PONG_INSTANCES_AMOUNT, + "Only " + PONG_INSTANCES_AMOUNT + " services should response"); + + for (Map.Entry pod : uniqueResp.entrySet()) { + Assertions.assertTrue(uniqueResp.get(pod.getKey()) >= roundRobinError, + "Request load is not distributed following a round-robin distribution"); + } + } + + private ValidatableResponse makePingCall(String subPath) { + return ping + .given() + .get("/ping/" + subPath).then() + .statusCode(HttpStatus.SC_OK); + } + + /** + * setup `stork-service-discovery-kubernetes` - roles and roles bindings (required) + */ + private static void setupClusterRoles() { + String namespace = openshift.project(); + String clusterRoleContent = FileUtils.loadFile(new File("target/test-classes/" + CLUSTER_ROLE_FILE_NAME)) + .replaceAll(quote("${NAMESPACE}"), namespace); + openshift.apply(FileUtils.copyContentTo(clusterRoleContent, + new File("target/test-classes/" + CLUSTER_ROLE_FILE_NAME).toPath())); + String contentRBAC = FileUtils.loadFile(new File("target/test-classes/" + RBAC_FILE_NAME)) + .replaceAll(quote("${NAMESPACE}"), namespace); + openshift.apply(FileUtils.copyContentTo(contentRBAC, new File("target/test-classes/" + RBAC_FILE_NAME).toPath())); + } +} diff --git a/service-discovery/stork-consul/src/test/java/io/quarkus/ts/stork/StorkServiceDiscoveryIT.java b/service-discovery/stork/src/test/java/io/quarkus/ts/stork/StorkServiceDiscoveryIT.java similarity index 95% rename from service-discovery/stork-consul/src/test/java/io/quarkus/ts/stork/StorkServiceDiscoveryIT.java rename to service-discovery/stork/src/test/java/io/quarkus/ts/stork/StorkServiceDiscoveryIT.java index 597f0cfe5..9e8717a80 100644 --- a/service-discovery/stork-consul/src/test/java/io/quarkus/ts/stork/StorkServiceDiscoveryIT.java +++ b/service-discovery/stork/src/test/java/io/quarkus/ts/stork/StorkServiceDiscoveryIT.java @@ -4,7 +4,6 @@ import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.greaterThanOrEqualTo; import static org.hamcrest.Matchers.is; -import static org.junit.jupiter.api.Assertions.fail; import java.io.IOException; import java.net.ServerSocket; @@ -21,6 +20,8 @@ import io.quarkus.test.services.Container; import io.quarkus.test.services.QuarkusApplication; +import junit.framework.AssertionFailedError; + @QuarkusScenario public class StorkServiceDiscoveryIT { @@ -122,14 +123,11 @@ private static String getConsultEndpoint(String endpoint) { return endpoint.replaceFirst(":\\d+", ""); } - private static String getAvailablePort() { - int port = 0; - try (ServerSocket serverSocket = new ServerSocket(port)) { - port = serverSocket.getLocalPort(); + public static String getAvailablePort() { + try (ServerSocket socket = new ServerSocket(0)) { + return String.valueOf(socket.getLocalPort()); } catch (IOException e) { - fail("no free port available."); + throw new AssertionFailedError(); } - - return String.valueOf(port); } } diff --git a/service-discovery/stork-consul/src/test/resources/cluster-role.yaml b/service-discovery/stork/src/test/resources/cluster-role.yaml similarity index 88% rename from service-discovery/stork-consul/src/test/resources/cluster-role.yaml rename to service-discovery/stork/src/test/resources/cluster-role.yaml index 77598d6d4..ad74137aa 100644 --- a/service-discovery/stork-consul/src/test/resources/cluster-role.yaml +++ b/service-discovery/stork/src/test/resources/cluster-role.yaml @@ -1,7 +1,7 @@ kind: ClusterRole apiVersion: rbac.authorization.k8s.io/v1 metadata: - namespace: default + namespace: "${NAMESPACE}" name: endpoints-reader rules: - apiGroups: [""] # "" indicates the core API group diff --git a/service-discovery/stork-consul/src/test/resources/fabric8-rbac.yaml b/service-discovery/stork/src/test/resources/fabric8-rbac.yaml similarity index 86% rename from service-discovery/stork-consul/src/test/resources/fabric8-rbac.yaml rename to service-discovery/stork/src/test/resources/fabric8-rbac.yaml index 273fa334a..6270952ab 100644 --- a/service-discovery/stork-consul/src/test/resources/fabric8-rbac.yaml +++ b/service-discovery/stork/src/test/resources/fabric8-rbac.yaml @@ -6,7 +6,6 @@ subjects: - kind: ServiceAccount # Reference to upper's `metadata.name` name: default - # Reference to upper's `metadata.namespace` namespace: "${NAMESPACE}" roleRef: kind: ClusterRole diff --git a/service-discovery/stork/src/test/resources/test.properties b/service-discovery/stork/src/test/resources/test.properties new file mode 100644 index 000000000..71b4dd3ad --- /dev/null +++ b/service-discovery/stork/src/test/resources/test.properties @@ -0,0 +1,2 @@ +ts.pung.openshift.use-internal-service-as-url=true +ts.pong.openshift.use-internal-service-as-url=true