Skip to content

Commit

Permalink
Cover separate management interface
Browse files Browse the repository at this point in the history
Now Quarkus can expose endpoints for metrics and health
on a separate network interface.
We verify, that this is supported, and we can use custom port, switch
HTTPS on and off and change api path.
This requires supports on the side of the FW and enabling one of the
disabled tests.

Test plans for the change: https://github.com/quarkus-qe/quarkus-test-plans/blob/main/QUARKUS-2738.md
Related links:
quarkusio/quarkus#30506
https://issues.redhat.com/browse/QUARKUS-2738
  • Loading branch information
fedinskiy committed Mar 30, 2023
1 parent 1bc8d3c commit 2b483fa
Show file tree
Hide file tree
Showing 14 changed files with 296 additions and 8 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -356,6 +356,9 @@ It also verifies multiple deployment strategies like:
- Using OpenShift quarkus extension
- Using OpenShift quarkus extension and Docker Build strategy

### `http/management`
Verifies, that management interface (micrometer metrics and health endpoints) can be hosted on a separate port

#### Additions
* *@Deprecated* annotation has been added for test regression purposes to ensure `java.lang` annotations are allowed for resources
* Resource with multipart body support, provided parts are text, image and binary data, charset checked with `us-ascii` and `utf-8`
Expand Down
47 changes: 47 additions & 0 deletions http/management/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>io.quarkus.ts.qe</groupId>
<artifactId>parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../..</relativePath>
</parent>
<artifactId>http-management</artifactId>
<packaging>jar</packaging>
<name>Quarkus QE TS: HTTP: Management Interface</name>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-resteasy</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-micrometer-registry-prometheus</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-openapi</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus.qe</groupId>
<artifactId>quarkus-test-openshift</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<profiles>
<profile>
<id>deploy-to-openshift-using-extension</id>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-openshift</artifactId>
</dependency>
</dependencies>
</profile>
</profiles>
</project>
16 changes: 16 additions & 0 deletions http/management/src/main/java/io/quarkus/qe/HttpResource.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package io.quarkus.qe;

import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/ping")
public class HttpResource {

@GET
@Produces(MediaType.TEXT_PLAIN)
public String pong() {
return "pong";
}
}
Binary file not shown.
3 changes: 3 additions & 0 deletions http/management/src/main/resources/application.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Only run tests annotated with @QuarkusTest
quarkus.test.type=quarkus-test
quarkus.management.enabled=true
57 changes: 57 additions & 0 deletions http/management/src/test/java/io/quarkus/qe/LocalEndpointsIT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package io.quarkus.qe;

import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertTrue;

import org.apache.http.HttpStatus;
import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.services.QuarkusApplication;
import io.restassured.response.Response;

@QuarkusScenario
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class LocalEndpointsIT {

@QuarkusApplication
static final RestService app = new RestService();

@Test
@Order(1)
public void greeting() {
Response response = app.given().get("/ping");
assertEquals(200, response.statusCode());
assertEquals("pong", response.body().asString());
}

@Test
public void health() {
app.management().get("q/health").then().statusCode(HttpStatus.SC_OK);
}

@Test
public void oldHealth() {
app.given().get("q/health").then().statusCode(HttpStatus.SC_NOT_FOUND);
}

@Test
public void metrics() {
Response response = app.management().get("q/metrics");
assertEquals(200, response.statusCode());
String metric = null;
String body = response.body().asString();
for (String line : body.split("\n")) {
if (line.contains("http_server_requests_seconds_count") && line.contains("SUCCESS")) {
metric = line;
}
}
assertNotNull(metric, "Metric 'http_server_requests_seconds_count' was not found in the response: " + body);
assertTrue(metric.endsWith("1.0"), "requests count is wrong: " + metric);
}
}
94 changes: 94 additions & 0 deletions http/management/src/test/java/io/quarkus/qe/LocalOptionsIT.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package io.quarkus.qe;

import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.Arrays;

import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Test;

import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.services.QuarkusApplication;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;

@QuarkusScenario
public class LocalOptionsIT {

@QuarkusApplication
static final RestService app = new RestService();

@QuarkusApplication
static final RestService custom = new RestService()
.withProperty("quarkus.management.port", "9002");

@QuarkusApplication
static final RestService tls = new RestService()
.withProperty("quarkus.management.port", "9003")
.withProperty("quarkus.management.ssl.certificate.key-store-file", "META-INF/resources/server.keystore")
.withProperty("quarkus.management.ssl.certificate.key-store-password", "password");

@QuarkusApplication
static final RestService unmanaged = new RestService()
.withProperty("quarkus.management.enabled", "false");

@QuarkusApplication
static final RestService redirected = new RestService()
.withProperty("quarkus.management.port", "9004")
.withProperty("quarkus.http.root-path", "/api")
.withProperty("quarkus.http.non-application-root-path", "/query")
.withProperty("quarkus.management.root-path", "management");

@Test
public void greeting() {
for (RestService service : Arrays.asList(app, custom, tls, unmanaged)) {
Response response = service.given().get("/ping");
assertEquals(200, response.statusCode());
assertEquals("pong", response.body().asString());

Response openapi = service.given().get("/q/openapi?format=json"); //openapi should be on the old interface
assertEquals(200, openapi.statusCode());
JsonPath json = openapi.body().jsonPath();
assertEquals("OK", json.getString("paths.\"/ping\".get.responses.\"200\".description"));
}
}

@Test
public void unmanaged() {
unmanaged.given().get("q/health").then().statusCode(HttpStatus.SC_OK);
}

@Test
public void managed() {
app.management().get("q/health").then().statusCode(HttpStatus.SC_OK);
}

@Test
public void customPort() {
custom.management()
.get("q/health").then().statusCode(HttpStatus.SC_OK);
}

@Test
public void tls() {
tls.management()
.relaxedHTTPSValidation()
.get("q/health").then().statusCode(HttpStatus.SC_OK);
}

@Test
public void redirected() {
Response response = redirected.given().get("api/ping");
assertEquals(200, response.statusCode());
assertEquals("pong", response.body().asString());

redirected.management().get("management/health").then()
.statusCode(HttpStatus.SC_OK);

Response openapi = redirected.given().get("query/openapi?format=json");
assertEquals(200, openapi.statusCode());
JsonPath json = openapi.body().jsonPath();
assertEquals("OK", json.getString("paths.\"/api/ping\".get.responses.\"200\".description"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.quarkus.qe;

import io.quarkus.test.scenarios.OpenShiftScenario;

@OpenShiftScenario
public class OpenShiftEndpointsIT extends LocalEndpointsIT {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package io.quarkus.qe;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.OpenShiftDeploymentStrategy;
import io.quarkus.test.scenarios.OpenShiftScenario;
import io.quarkus.test.services.QuarkusApplication;
import io.restassured.response.Response;

@OpenShiftScenario(deployment = OpenShiftDeploymentStrategy.UsingOpenShiftExtension)
@Disabled("Requires fixing https://github.com/quarkusio/quarkus/issues/32135 and changes in the Framework")
public class OpenShiftExtensionIT {
@QuarkusApplication
static final RestService app = new RestService();

@Test
public void payload() {
Response response = app.given().get("/ping");
assertEquals(200, response.statusCode());
assertEquals("pong", response.body().asString());
}

@Test
public void health() {
app.management().get("q/health").then().statusCode(HttpStatus.SC_OK);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package io.quarkus.qe;

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import io.quarkus.test.scenarios.OpenShiftScenario;

@OpenShiftScenario
public class OpenShiftOptionsIT extends LocalOptionsIT {
@Test
@Override
@Disabled("SSL on openshift is not supported by the FW (yet)")
public void tls() {
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
quarkus.openshift.labels.app-with-metrics=quarkus-app

# MP Integration
quarkus.micrometer.binder.mp-metrics.enabled=true
quarkus.micrometer.binder.mp-metrics.enabled=true
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@
import org.apache.http.HttpStatus;
import org.junit.jupiter.api.Test;

import io.quarkus.test.bootstrap.RestService;
import io.quarkus.test.scenarios.QuarkusScenario;
import io.quarkus.test.services.QuarkusApplication;

@QuarkusScenario
public class HttpServerMetricsIT {
Expand All @@ -31,6 +33,10 @@ public class HttpServerMetricsIT {
private static final String HTTP_SERVER_REQUESTS_METRICS_FORMAT = "http_server_requests_seconds_%s{method=\"GET\",outcome=\"SUCCESS\",status=\"200\",uri=\"%s\"";
private static final String PING_PONG_ENDPOINT = "/without-metrics-pingpong";

@QuarkusApplication
static RestService app = new RestService()
.withProperty("quarkus.management.enabled", "true");

@Test
public void testHttpServerRequestsCountShouldBeRegistered() {
thenHttpServerRequestsMetricsAreNotPresent();
Expand All @@ -47,7 +53,7 @@ private void whenCallPingPong() {
}

private void thenHttpServerRequestsMetricsAreNotPresent() {
String metrics = when().get("/q/metrics").then()
String metrics = app.management().get("/q/metrics").then()
.statusCode(HttpStatus.SC_OK).extract().asString();

for (String metricSuffix : HTTP_SERVER_REQUESTS_METRICS_SUFFIX) {
Expand All @@ -57,7 +63,7 @@ private void thenHttpServerRequestsMetricsAreNotPresent() {
}

private void thenHttpServerRequestsMetricsArePresent() {
String metrics = when().get("/q/metrics").then()
String metrics = app.management().get("/q/metrics").then()
.statusCode(HttpStatus.SC_OK).extract().asString();

for (String metricSuffix : HTTP_SERVER_REQUESTS_METRICS_SUFFIX) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@
import org.apache.http.HttpStatus;
import org.jboss.logging.Logger;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import io.quarkus.test.bootstrap.RestService;
Expand All @@ -27,7 +26,6 @@
* - `prime_number_max_{uniqueId}`: max prime number that is found.
* - `prime_number_test_{uniqueId}`: with information about the calculation of the prime number.
*/
@Disabled("https://github.com/quarkusio/quarkus/issues/31228")
@OpenShiftScenario(deployment = OpenShiftDeploymentStrategy.UsingOpenShiftExtension)
public class OpenShiftCustomMetricsIT {

Expand All @@ -51,7 +49,16 @@ public class OpenShiftCustomMetricsIT {
static final Integer ANY_VALUE = null;

@QuarkusApplication
static RestService app = new RestService().onPostStart(OpenShiftCustomMetricsIT::loadServiceMonitor);
static RestService app = new RestService()
/*
* TODO fix deployment with OpenShiftDeploymentStrategies in the Framework
* see https://github.com/quarkusio/quarkus/issues/32135#issuecomment-1486740862 for details
* .withProperty("quarkus.management.ssl.certificate.key-store-file",
* "META-INF/resources/server.keystore")
* .withProperty("quarkus.management.ssl.certificate.key-store-password", "password")
* .withProperty("quarkus.management.enabled", "true")
*/
.onPostStart(OpenShiftCustomMetricsIT::loadServiceMonitor);

@Inject
static OpenShiftClient client;
Expand Down Expand Up @@ -121,7 +128,7 @@ private void thenMetricIsExposedInServiceEndpoint(String name, Integer expected)
shouldContain += " " + expected;
}

app.given().get("/q/metrics").then()
app.management().get("/q/metrics").then()
.statusCode(HttpStatus.SC_OK)
.body(containsString(shouldContain));
});
Expand Down
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
<quarkus.platform.version>999-SNAPSHOT</quarkus.platform.version>
<quarkus.qe.framework.version>1.3.0.Beta9</quarkus.qe.framework.version>
<quarkus.qe.framework.version>1.3.0.Beta10</quarkus.qe.framework.version>
<quarkus-qpid-jms.version>0.42.0</quarkus-qpid-jms.version>
<quarkus-ide-config.version>2.12.1.Final</quarkus-ide-config.version>
<apache-httpclient-fluent.version>4.5.14</apache-httpclient-fluent.version>
Expand Down Expand Up @@ -451,6 +451,7 @@
<module>http/graphql</module>
<module>http/graphql-telemetry</module>
<module>http/vertx</module>
<module>http/management</module>
</modules>
</profile>
<profile>
Expand Down

0 comments on commit 2b483fa

Please sign in to comment.