Skip to content

Commit

Permalink
[WFLY-12342] Add server probes for readiness health check
Browse files Browse the repository at this point in the history
Changes relater to WFLY-12342:
- adjust existing tests to work with new changes
- added new tests for new fetures in WFLY-12342
  • Loading branch information
Martin Choma authored and mnovak1 committed Oct 20, 2020
1 parent ef9d7c5 commit 9efd68f
Show file tree
Hide file tree
Showing 15 changed files with 198 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,29 @@
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.notNullValue;
import static org.hamcrest.Matchers.nullValue;
import static org.jboss.eap.qe.microprofile.tooling.server.configuration.creaper.ManagementClientHelper.executeCliCommand;

import java.io.IOException;
import java.util.concurrent.TimeoutException;

import org.apache.http.HttpStatus;
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.eap.qe.microprofile.health.tools.HealthUrlProvider;
import org.jboss.eap.qe.microprofile.tooling.server.configuration.ConfigurationException;
import org.jboss.eap.qe.microprofile.tooling.server.configuration.creaper.ManagementClientProvider;
import org.jboss.eap.qe.microprofile.tooling.server.configuration.creaper.ManagementClientRelatedException;
import org.jboss.shrinkwrap.api.Archive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.wildfly.extras.creaper.core.online.OnlineManagementClient;
import org.wildfly.extras.creaper.core.online.operations.admin.Administration;

import io.restassured.RestAssured;
import io.restassured.http.ContentType;
Expand All @@ -37,6 +47,7 @@
public class DefaultReadinessProcedureHealthTest {

public static final String ARCHIVE_NAME = DefaultReadinessProcedureHealthTest.class.getSimpleName() + ".war";
private final String CHANGE_H2_DRIVER_NAME_CLI = "/subsystem=datasources/data-source=ExampleDS:write-attribute(name=driver-name, value=%s)";

@Deployment(testable = false)
public static Archive<?> deployment() {
Expand All @@ -47,24 +58,30 @@ public static Archive<?> deployment() {

/**
* @tpTestDetails Calls the deprecated {@code health} endpoint to get response from all health check procedures
* @tpPassCrit Overall health check status is up and two checks are expected to be returned: one {@code liveness}
* @tpPassCrit Overall health check status is up and five checks are expected to be returned: one {@code liveness}
* check - which is defined by the {@link LivenessHealthCheck} annotated class and has "UP" status and data -
* and
* one {@code readiness} check - which is provided by Wildfly because none was defined in the deployment and the
* {@code mp.health.disable-default-procedures} being set to {@code false} by default. This last check must be
* conventionally named after the deplyment name - i.e namely: {@code "ready-deployment." + deployment name}
* With WFLY-12342 There was also added {@code deployments-status}, {@code boot-errors}, {@code server-state}
* checks
* @tpSince EAP 7.4.0.CD19
*/
@Test
public void testHealthEndpoint() throws ConfigurationException {
RestAssured.get(HealthUrlProvider.healthEndpoint()).then()
.assertThat()
.statusCode(HttpStatus.SC_OK)
.contentType(ContentType.JSON)
.body("status", is("UP"),
"checks", hasSize(2),
"checks", hasSize(5),
"checks.status", hasItems("UP", "UP"),
"checks.name", containsInAnyOrder(String.format("ready-deployment.%s", ARCHIVE_NAME), "live"),
"checks.data", hasSize(2),
"checks.data.key", contains("value"));
"checks.name",
containsInAnyOrder("deployments-status", "boot-errors", "server-state",
String.format("ready-deployment.%s", ARCHIVE_NAME), "live"),
"checks.data", hasSize(5),
"checks.find{it.name == 'live'}.data.key", is("value"));
}

/**
Expand All @@ -89,20 +106,107 @@ public void testLivenessEndpoint() throws ConfigurationException {

/**
* @tpTestDetails Calls the {@code ready} endpoint to get response from all {@code readiness} procedures
* @tpPassCrit Overall health check status is up and one check is expected to be returned, i.e the {@code readiness}
* @tpPassCrit Overall health check status is up and four check are expected to be returned, i.e the {@code readiness}
* check which is provided by Wildfly because none was defined in the deployment and the
* {@code mp.health.disable-default-procedures} being set to {@code false} by default. It must be
* conventionally named after the deplyment name - i.e namely: {@code "ready-deployment." + deployment name}
* @tpSince EAP 7.4.0.CD19
*/
@Test
public void testReadinessEndpoint() throws ConfigurationException {
String readyDeploymentCheckName = String.format("ready-deployment.%s", ARCHIVE_NAME);
RestAssured.get(HealthUrlProvider.readyEndpoint()).then()
.contentType(ContentType.JSON)
.body("status", is("UP"),
"checks", hasSize(1),
"checks", hasSize(4),
"checks.status", hasItems("UP"),
"checks.name", contains(String.format("ready-deployment.%s", ARCHIVE_NAME)),
"checks.data", contains(nullValue()));
"checks.name",
containsInAnyOrder("boot-errors", "server-state", "deployments-status",
readyDeploymentCheckName),
"checks.find{it.name == '" + readyDeploymentCheckName + "'}.data", is(nullValue()),
"checks.find{it.name == 'boot-errors'}.data", is(nullValue()),
"checks.find{it.name == 'deployments-status'}.data", is(notNullValue()),
"checks.find{it.name == 'server-state'}.data.value", is("running"));
}

/**
* @tpTestDetails Calls the {@code ready} endpoint to get response from all {@code readiness} procedures. We have
* introduced change which switch server to {@code reload-required} change.
* @tpPassCrit Overall health check status is down and {@code server-state} readiness check is DOWN
* @tpSince EAP 7.4.0.CD21
*/
@Test
public void testServerStateDown() throws ConfigurationException, IOException, ManagementClientRelatedException {
OnlineManagementClient client = ManagementClientProvider.onlineStandalone();
try {
executeCliCommand(client, String.format(CHANGE_H2_DRIVER_NAME_CLI, "wrong_driver_name"));

RestAssured.get(HealthUrlProvider.readyEndpoint()).then()
.contentType(ContentType.JSON)
.body("status", is("DOWN"),
"checks.find{it.name == 'server-state'}.status", is("DOWN"),
"checks.find{it.name == 'deployments-status'}.status", is("UP"),
"checks.find{it.name == 'boot-errors'}.status", is("UP"),
"checks.find{it.name == 'server-state'}.data.value", is("reload-required"));

} finally {
// put back configuration to correct form
executeCliCommand(client, String.format(CHANGE_H2_DRIVER_NAME_CLI, "h2"));
client.close();
}
}

/**
* @tpTestDetails Calls the {@code ready} endpoint to get response from all {@code readiness} procedures. Wrong
* configuration change is introduced which emits exception in server start
* @tpPassCrit Overall health check status is down and {@code boot-errors} readiness check is DOWN
* @tpSince EAP 7.4.0.CD21
*/
@Test
public void testBootErrorsDown() throws ConfigurationException, IOException, ManagementClientRelatedException,
TimeoutException, InterruptedException {
OnlineManagementClient client = ManagementClientProvider.onlineStandalone();
try {
executeCliCommand(client, String.format(CHANGE_H2_DRIVER_NAME_CLI, "wrong_driver_name"));
new Administration(client).reloadIfRequired();

RestAssured.get(HealthUrlProvider.readyEndpoint()).then()
.contentType(ContentType.JSON)
.body("status", is("DOWN"),
"checks.find{it.name == 'boot-errors'}.status", is("DOWN"),
"checks.find{it.name == 'server-state'}.status", is("UP"),
"checks.find{it.name == 'deployments-status'}.status", is("DOWN"),
"checks.find{it.name == 'boot-errors'}.data", is(notNullValue()));
} finally {
// put back configuration to correct form
executeCliCommand(client, String.format(CHANGE_H2_DRIVER_NAME_CLI, "h2"));
new Administration(client).reloadIfRequired();
client.close();
}
}

/**
* @tpTestDetails Calls the {@code ready} endpoint to get response from all {@code readiness} procedures. There is
* one STOPPED deployment which cause deployments-status to be DOWN.
* @tpPassCrit Overall health check status is down and {@code deployments-status} readiness check is DOWN
* @tpSince EAP 7.4.0.CD21
*/
@Test
public void testDeploymentsStatusDown() throws ConfigurationException, IOException, ManagementClientRelatedException {
OnlineManagementClient client = ManagementClientProvider.onlineStandalone();
try {
executeCliCommand(client, "deployment disable " + ARCHIVE_NAME);

RestAssured.get(HealthUrlProvider.readyEndpoint()).then()
.contentType(ContentType.JSON)
.body("status", is("DOWN"),
"checks.find{it.name == 'deployments-status'}.status", is("DOWN"),
"checks.find{it.name == 'server-state'}.status", is("UP"),
"checks.find{it.name == 'boot-errors'}.status", is("UP"),
"checks.find{it.name == 'deployments-status'}.data", is(notNullValue()));
} finally {
executeCliCommand(client, "deployment enable " + ARCHIVE_NAME);
client.close();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.jboss.eap.qe.microprofile.health;

import org.jboss.eap.qe.microprofile.tooling.server.configuration.arquillian.MicroProfileServerSetupTask;
import org.jboss.eap.qe.microprofile.tooling.server.configuration.creaper.ManagementClientProvider;
import org.wildfly.extras.creaper.core.online.OnlineManagementClient;
import org.wildfly.extras.creaper.core.online.operations.admin.Administration;

/**
* Add system property {@code MP_HEALTH_DISABLE_DEFAULT_PROCEDURES} for MP Health to disable vendor specific checks
*/
public class DisableDefaultHealthProceduresSetupTask implements MicroProfileServerSetupTask {

public static final String MP_HEALTH_DISABLE_DEFAULT_PROCEDURES = "mp.health.disable-default-procedures";

@Override
public void setup() throws Exception {
try (OnlineManagementClient client = ManagementClientProvider.onlineStandalone()) {
client.execute(String.format("/system-property=%s:add(value=true)", MP_HEALTH_DISABLE_DEFAULT_PROCEDURES))
.assertSuccess();
new Administration(client).reload();
}
}

@Override
public void tearDown() throws Exception {
try (OnlineManagementClient client = ManagementClientProvider.onlineStandalone()) {
client.execute(String.format("/system-property=%s:remove", MP_HEALTH_DISABLE_DEFAULT_PROCEDURES))
.assertSuccess();
new Administration(client).reload();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.as.arquillian.api.ServerSetup;
import org.jboss.eap.qe.microprofile.health.tools.HealthUrlProvider;
import org.jboss.eap.qe.microprofile.tooling.server.configuration.ConfigurationException;
import org.jboss.shrinkwrap.api.Archive;
Expand All @@ -23,6 +24,7 @@

@RunAsClient
@RunWith(Arquillian.class)
@ServerSetup({ DisableDefaultHealthProceduresSetupTask.class })
public class HealthDeprecatedTest {

@Deployment(testable = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.as.arquillian.api.ServerSetup;
import org.jboss.eap.qe.microprofile.health.tools.HealthUrlProvider;
import org.jboss.eap.qe.microprofile.tooling.server.configuration.ConfigurationException;
import org.jboss.shrinkwrap.api.Archive;
Expand All @@ -22,6 +23,7 @@

@RunAsClient
@RunWith(Arquillian.class)
@ServerSetup({ DisableDefaultHealthProceduresSetupTask.class })
public class HealthNullTest {

@Deployment(testable = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.as.arquillian.api.ServerSetup;
import org.jboss.eap.qe.microprofile.health.tools.HealthUrlProvider;
import org.jboss.eap.qe.microprofile.tooling.server.configuration.ConfigurationException;
import org.jboss.shrinkwrap.api.Archive;
Expand All @@ -24,6 +25,7 @@

@RunAsClient
@RunWith(Arquillian.class)
@ServerSetup({ DisableDefaultHealthProceduresSetupTask.class })
public class HealthTest {

@Deployment(testable = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.as.arquillian.api.ServerSetup;
import org.jboss.eap.qe.microprofile.health.tools.HealthUrlProvider;
import org.jboss.eap.qe.microprofile.tooling.server.configuration.ConfigurationException;
import org.jboss.shrinkwrap.api.Archive;
Expand All @@ -24,6 +25,7 @@

@RunAsClient
@RunWith(Arquillian.class)
@ServerSetup({ DisableDefaultHealthProceduresSetupTask.class })
public class MimeTypeHealthTest {

@Deployment(testable = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.as.arquillian.api.ServerSetup;
import org.jboss.eap.qe.microprofile.health.tools.HealthUrlProvider;
import org.jboss.eap.qe.microprofile.tooling.server.configuration.ConfigurationException;
import org.jboss.shrinkwrap.api.Archive;
Expand All @@ -26,6 +27,7 @@
* Multiple deployment scenario.
*/
@RunWith(Arquillian.class)
@ServerSetup({ DisableDefaultHealthProceduresSetupTask.class })
public class MultiDeploymentHealthTest {

@Deployment(name = "deployment1", order = 1, testable = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import org.jboss.arquillian.container.test.api.Deployment;
import org.jboss.arquillian.container.test.api.RunAsClient;
import org.jboss.arquillian.junit.Arquillian;
import org.jboss.as.arquillian.api.ServerSetup;
import org.jboss.eap.qe.microprofile.health.tools.HealthUrlProvider;
import org.jboss.eap.qe.microprofile.tooling.server.configuration.ConfigurationException;
import org.jboss.shrinkwrap.api.Archive;
Expand All @@ -24,6 +25,7 @@

@RunAsClient
@RunWith(Arquillian.class)
@ServerSetup({ DisableDefaultHealthProceduresSetupTask.class })
public class SimplifiedHealthTest {

@Deployment(testable = false)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,8 @@ public void delayedConstructorTest()
get(HealthUrlProvider.readyEndpoint(arqProps)).then()
.statusCode(503)
.body("status", is("DOWN"),
"checks.name", containsInAnyOrder(DelayedReadinessHealthCheck.NAME));
"checks.name", containsInAnyOrder(DelayedReadinessHealthCheck.NAME, "deployments-status",
"boot-errors", "server-state"));
} finally {
controller.stop(ManualTests.ARQUILLIAN_CONTAINER);
}
Expand Down Expand Up @@ -300,7 +301,8 @@ public void unexpectedHealthChecksTest()
.statusCode(200)
.body("status", is("UP"),
"checks.name", containsInAnyOrder(
"ready-deployment." + DelayedLivenessHealthCheck.class.getSimpleName() + ".war"));
"ready-deployment." + DelayedLivenessHealthCheck.class.getSimpleName() + ".war",
"deployments-status", "boot-errors", "server-state"));
} finally {
controller.stop(ManualTests.ARQUILLIAN_CONTAINER);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,20 +51,20 @@ public Boolean call() {
if (response.getStatusCode() == 503) {
if (checks == null) {
addState(DOWN_NO_CONTENT());
} else if (checks.size() == 0) {
} else if ((checks.size() == 4) && contains(checks, "empty-readiness-checks")) {
addState(DOWN_NO_CHECK());
} else if (checks.get(0).get("name").equals(DelayedReadinessHealthCheck.NAME)) {
} else if ((checks.size() == 4) && contains(checks, DelayedReadinessHealthCheck.NAME)) {
addState(ReadinessState.DOWN_WITH_CHECK());
}
} else if (response.getStatusCode() == 200) {
if (checks == null) {
throw new RuntimeException("Readiness probe is UP (200) however missing JSON content");
}
if (checks.size() == 0) {
if ((checks.size() == 4) && contains(checks, "empty-readiness-checks")) {
addState(UP_NO_CHECK());
} else if (checks.get(0).get("name").equals(DelayedReadinessHealthCheck.NAME)) {
} else if ((checks.size() == 4) && contains(checks, DelayedReadinessHealthCheck.NAME)) {
addState(UP_WITH_CHECK());
} else if (checks.get(0).get("name").startsWith(DEFAULT_READINESS_CHECK_NAME_PREFIX)) {
} else if ((checks.size() == 4) && contains(checks, DEFAULT_READINESS_CHECK_NAME_PREFIX)) {
addState(UP_WITH_DEFAULT_CHECK());
}
}
Expand Down Expand Up @@ -92,6 +92,23 @@ private int lastIndexOfStates() {
return states.size() - 1;
}

/**
* @param list collection to find in
* @param key which we are looking for
* @return true if key {@code name} atribute startsWith {@code key}. False otherwise.
*/
private boolean contains(List<Map<String, String>> list, String key) {
if (list == null) {
return false;
}
for (Map<String, String> item : list) {
if (item.get("name").startsWith(key)) {
return true;
}
}
return false;
}

public void stop() {
shouldStop.set(true);
}
Expand Down
Loading

0 comments on commit 9efd68f

Please sign in to comment.