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 committed Sep 24, 2020
1 parent db875d1 commit d5393bd
Show file tree
Hide file tree
Showing 15 changed files with 198 additions and 27 deletions.
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
package org.jboss.eap.qe.microprofile.health;

import static org.hamcrest.Matchers.contains;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.hasItems;
import static org.hamcrest.Matchers.hasSize;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.nullValue;
import static org.hamcrest.Matchers.*;
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 +41,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 +52,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 +100,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 d5393bd

Please sign in to comment.