This is an automated email from the ASF dual-hosted git repository. ycai pushed a commit to branch trunk in repository https://gitbox.apache.org/repos/asf/cassandra-sidecar.git
The following commit(s) were added to refs/heads/trunk by this push: new 5d2cbaf CASSANDRASC-50: Deprecate the sidecar cassandra health endpoint containing instance segment 5d2cbaf is described below commit 5d2cbaf5cb810f53689bf227e2c1f78a9a2b2e9f Author: Francisco Guerrero <francisco.guerr...@apple.com> AuthorDate: Fri May 5 10:48:02 2023 -0700 CASSANDRASC-50: Deprecate the sidecar cassandra health endpoint containing instance segment This commit deprecates the Cassandra Health endpoint containing the instance segment in the path. This endpoint is currently unused and it is replaced by the health endpoint with the `instanceId` query string parameter. Since the `instanceId` is optional we move the path param (mandatory) to the query param (optional). This commit also moves the CassandraHealthService from jax RS to a vertx Handler. It also moves the HealthService to a inlined handler, simplifying the service. patch by Francisco Guerrero; reviewed by Yifan Cai, Dinesh Joshi for CASSANDRASC-50 --- CHANGES.txt | 1 + .../cassandra/sidecar/common/ApiEndpointsV1.java | 4 + .../org/apache/cassandra/sidecar/MainModule.java | 23 ++++-- .../cassandra/sidecar/cluster/InstancesConfig.java | 7 +- .../sidecar/cluster/InstancesConfigImpl.java | 12 ++- .../cassandra/sidecar/routes/AbstractHandler.java | 4 +- .../sidecar/routes/CassandraHealthHandler.java | 93 ++++++++++++++++++++++ .../cassandra/sidecar/routes/HealthService.java | 50 ------------ .../sidecar/routes/SwaggerOpenApiResource.java | 3 +- .../sidecar/utils/InstanceMetadataFetcher.java | 4 +- .../routes/SnapshotsHandlerIntegrationTest.java | 30 +++---- .../sidecar/AbstractHealthServiceTest.java | 31 ++++---- 12 files changed, 159 insertions(+), 103 deletions(-) diff --git a/CHANGES.txt b/CHANGES.txt index aec5dc7..73870a7 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,6 @@ 1.0.0 ----- + * Deprecate the sidecar cassandra health endpoint containing instance segment (CASSANDRASC-50) * Add an endpoint that gives information about the release version & partitioner name of a node (CASSANDRASC-48) * Introduce JMX foundation in Sidecar (CASSANDRASC-47) * Delegate methods to the RateLimiter (CASSANDRASC-45) diff --git a/common/src/main/java/org/apache/cassandra/sidecar/common/ApiEndpointsV1.java b/common/src/main/java/org/apache/cassandra/sidecar/common/ApiEndpointsV1.java index e159433..f68c469 100644 --- a/common/src/main/java/org/apache/cassandra/sidecar/common/ApiEndpointsV1.java +++ b/common/src/main/java/org/apache/cassandra/sidecar/common/ApiEndpointsV1.java @@ -26,6 +26,7 @@ public final class ApiEndpointsV1 public static final String API = "/api"; public static final String API_V1 = API + "/v1"; + public static final String HEALTH = "/__health"; public static final String CASSANDRA = "/cassandra"; public static final String KEYSPACE_PATH_PARAM = ":keyspace"; public static final String TABLE_PATH_PARAM = ":table"; @@ -39,6 +40,9 @@ public final class ApiEndpointsV1 public static final String PER_COMPONENT = "/components/" + COMPONENT_PATH_PARAM; public static final String PER_UPLOAD = "/uploads/" + UPLOAD_ID_PATH_PARAM; + public static final String HEALTH_ROUTE = API_V1 + HEALTH; + public static final String CASSANDRA_HEALTH_ROUTE = API_V1 + CASSANDRA + HEALTH; + @Deprecated // NOTE: Uses singular forms of "keyspace" and "table" public static final String DEPRECATED_SNAPSHOTS_ROUTE = API_V1 + "/keyspace/" + KEYSPACE_PATH_PARAM + "/table/" + TABLE_PATH_PARAM + diff --git a/src/main/java/org/apache/cassandra/sidecar/MainModule.java b/src/main/java/org/apache/cassandra/sidecar/MainModule.java index 581692b..fa0e196 100644 --- a/src/main/java/org/apache/cassandra/sidecar/MainModule.java +++ b/src/main/java/org/apache/cassandra/sidecar/MainModule.java @@ -19,6 +19,8 @@ package org.apache.cassandra.sidecar; import java.io.IOException; +import java.util.Collections; +import java.util.Map; import java.util.concurrent.TimeUnit; import com.google.common.util.concurrent.SidecarRateLimiter; @@ -46,10 +48,9 @@ import org.apache.cassandra.sidecar.common.CassandraVersionProvider; import org.apache.cassandra.sidecar.common.dns.DnsResolver; import org.apache.cassandra.sidecar.common.utils.ValidationConfiguration; import org.apache.cassandra.sidecar.logging.SidecarLoggerHandler; -import org.apache.cassandra.sidecar.routes.CassandraHealthService; +import org.apache.cassandra.sidecar.routes.CassandraHealthHandler; import org.apache.cassandra.sidecar.routes.FileStreamHandler; import org.apache.cassandra.sidecar.routes.GossipInfoHandler; -import org.apache.cassandra.sidecar.routes.HealthService; import org.apache.cassandra.sidecar.routes.JsonErrorHandler; import org.apache.cassandra.sidecar.routes.RingHandler; import org.apache.cassandra.sidecar.routes.SchemaHandler; @@ -73,6 +74,9 @@ import org.jboss.resteasy.plugins.server.vertx.VertxResteasyDeployment; */ public class MainModule extends AbstractModule { + public static final Map<String, String> OK_STATUS = Collections.singletonMap("status", "OK"); + public static final Map<String, String> NOT_OK_STATUS = Collections.singletonMap("status", "NOT_OK"); + @Provides @Singleton public Vertx vertx() @@ -114,17 +118,12 @@ public class MainModule extends AbstractModule @Provides @Singleton - private VertxRequestHandler configureServices(Vertx vertx, - HealthService healthService, - CassandraHealthService cassandraHealthService) + private VertxRequestHandler configureServices(Vertx vertx) { VertxResteasyDeployment deployment = new VertxResteasyDeployment(); deployment.start(); VertxRegistry registry = deployment.getRegistry(); - registry.addPerInstanceResource(SwaggerOpenApiResource.class); - registry.addSingletonResource(healthService); - registry.addSingletonResource(cassandraHealthService); return new VertxRequestHandler(vertx, deployment); } @@ -133,6 +132,7 @@ public class MainModule extends AbstractModule @Singleton public Router vertxRouter(Vertx vertx, Configuration conf, + CassandraHealthHandler cassandraHealthHandler, StreamSSTableComponentHandler streamSSTableComponentHandler, FileStreamHandler fileStreamHandler, SnapshotsHandler snapshotsHandler, @@ -170,6 +170,13 @@ public class MainModule extends AbstractModule .handler(docs); // Add custom routers + // Provides a simple REST endpoint to determine if Sidecar is available + router.get(ApiEndpointsV1.HEALTH_ROUTE) + .handler(context -> context.json(OK_STATUS)); + + router.get(ApiEndpointsV1.CASSANDRA_HEALTH_ROUTE) + .handler(cassandraHealthHandler); + //noinspection deprecation router.get(ApiEndpointsV1.DEPRECATED_COMPONENTS_ROUTE) .handler(streamSSTableComponentHandler) diff --git a/src/main/java/org/apache/cassandra/sidecar/cluster/InstancesConfig.java b/src/main/java/org/apache/cassandra/sidecar/cluster/InstancesConfig.java index a15d706..cf19a06 100644 --- a/src/main/java/org/apache/cassandra/sidecar/cluster/InstancesConfig.java +++ b/src/main/java/org/apache/cassandra/sidecar/cluster/InstancesConfig.java @@ -19,6 +19,7 @@ package org.apache.cassandra.sidecar.cluster; import java.util.List; +import java.util.NoSuchElementException; import org.apache.cassandra.sidecar.cluster.instance.InstanceMetadata; @@ -37,14 +38,16 @@ public interface InstancesConfig * * @param id instance's id * @return instance meta information + * @throws NoSuchElementException when the instance with {@code id} does not exist */ - InstanceMetadata instanceFromId(final int id); + InstanceMetadata instanceFromId(int id) throws NoSuchElementException; /** * Lookup instance metadata by host name. * * @param host host address of instance * @return instance meta information + * @throws NoSuchElementException when the instance for {@code host} does not exist */ - InstanceMetadata instanceFromHost(final String host); + InstanceMetadata instanceFromHost(String host) throws NoSuchElementException; } diff --git a/src/main/java/org/apache/cassandra/sidecar/cluster/InstancesConfigImpl.java b/src/main/java/org/apache/cassandra/sidecar/cluster/InstancesConfigImpl.java index ba5a488..0fcda22 100644 --- a/src/main/java/org/apache/cassandra/sidecar/cluster/InstancesConfigImpl.java +++ b/src/main/java/org/apache/cassandra/sidecar/cluster/InstancesConfigImpl.java @@ -21,6 +21,7 @@ package org.apache.cassandra.sidecar.cluster; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.NoSuchElementException; import java.util.function.Function; import java.util.stream.Collectors; @@ -51,27 +52,30 @@ public class InstancesConfigImpl implements InstancesConfig this.instanceMetadataList = instanceMetadataList; } + @Override public List<InstanceMetadata> instances() { return instanceMetadataList; } - public InstanceMetadata instanceFromId(int id) + @Override + public InstanceMetadata instanceFromId(int id) throws NoSuchElementException { InstanceMetadata instanceMetadata = idToInstanceMetadata.get(id); if (instanceMetadata == null) { - throw new IllegalArgumentException("Instance id " + id + " not found"); + throw new NoSuchElementException("Instance id " + id + " not found"); } return instanceMetadata; } - public InstanceMetadata instanceFromHost(String host) + @Override + public InstanceMetadata instanceFromHost(String host) throws NoSuchElementException { InstanceMetadata instanceMetadata = hostToInstanceMetadata.get(host); if (instanceMetadata == null) { - throw new IllegalArgumentException("Instance with host address " + host + " not found"); + throw new NoSuchElementException("Instance with host address " + host + " not found"); } return instanceMetadata; } diff --git a/src/main/java/org/apache/cassandra/sidecar/routes/AbstractHandler.java b/src/main/java/org/apache/cassandra/sidecar/routes/AbstractHandler.java index e46c812..78c8b24 100644 --- a/src/main/java/org/apache/cassandra/sidecar/routes/AbstractHandler.java +++ b/src/main/java/org/apache/cassandra/sidecar/routes/AbstractHandler.java @@ -18,6 +18,8 @@ package org.apache.cassandra.sidecar.routes; +import java.util.NoSuchElementException; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -138,7 +140,7 @@ public abstract class AbstractHandler<T> implements Handler<RoutingContext> throw new HttpException(HttpResponseStatus.BAD_REQUEST.code(), "InstanceId query parameter must be a valid integer"); } - catch (IllegalArgumentException | IllegalStateException ex) + catch (NoSuchElementException | IllegalStateException ex) { throw new HttpException(HttpResponseStatus.NOT_FOUND.code(), ex.getMessage()); } diff --git a/src/main/java/org/apache/cassandra/sidecar/routes/CassandraHealthHandler.java b/src/main/java/org/apache/cassandra/sidecar/routes/CassandraHealthHandler.java new file mode 100644 index 0000000..8530015 --- /dev/null +++ b/src/main/java/org/apache/cassandra/sidecar/routes/CassandraHealthHandler.java @@ -0,0 +1,93 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.cassandra.sidecar.routes; + +import com.google.inject.Inject; +import com.google.inject.Singleton; +import io.netty.handler.codec.http.HttpResponseStatus; +import io.vertx.core.http.HttpHeaders; +import io.vertx.core.http.HttpServerRequest; +import io.vertx.core.json.Json; +import io.vertx.core.net.SocketAddress; +import io.vertx.ext.web.RoutingContext; +import org.apache.cassandra.sidecar.common.CassandraAdapterDelegate; +import org.apache.cassandra.sidecar.common.utils.CassandraInputValidator; +import org.apache.cassandra.sidecar.concurrent.ExecutorPools; +import org.apache.cassandra.sidecar.utils.InstanceMetadataFetcher; + +import static org.apache.cassandra.sidecar.MainModule.NOT_OK_STATUS; +import static org.apache.cassandra.sidecar.MainModule.OK_STATUS; + +/** + * Provides a simple REST endpoint to determine if a Cassandra node is available + */ +@Singleton +public class CassandraHealthHandler extends AbstractHandler<Void> +{ + /** + * Constructs a handler with the provided {@code metadataFetcher} + * + * @param metadataFetcher the interface to retrieve instance metadata + * @param executorPools the executor pools for blocking executions + * @param validator a validator instance to validate Cassandra-specific input + */ + @Inject + protected CassandraHealthHandler(InstanceMetadataFetcher metadataFetcher, + ExecutorPools executorPools, + CassandraInputValidator validator) + { + super(metadataFetcher, executorPools, validator); + } + + /** + * Handles the request with the parameters for this request. + * + * @param context the request context + * @param httpRequest the {@link HttpServerRequest} object + * @param host the host where this request is intended for + * @param remoteAddress the address where the request originates + * @param request the request object + */ + @Override + protected void handleInternal(RoutingContext context, + HttpServerRequest httpRequest, + String host, + SocketAddress remoteAddress, + Void request) + { + CassandraAdapterDelegate delegate = metadataFetcher.delegate(host); + if (delegate != null && delegate.isUp()) + { + context.json(OK_STATUS); + } + else + { + context.response() + .setStatusCode(HttpResponseStatus.SERVICE_UNAVAILABLE.code()) + .putHeader(HttpHeaders.CONTENT_TYPE.toString(), "application/json") + .end(Json.CODEC.toString(NOT_OK_STATUS, false)); + } + } + + @Override + protected Void extractParamsOrThrow(RoutingContext context) + { + return null; + } +} diff --git a/src/main/java/org/apache/cassandra/sidecar/routes/HealthService.java b/src/main/java/org/apache/cassandra/sidecar/routes/HealthService.java deleted file mode 100644 index 4620693..0000000 --- a/src/main/java/org/apache/cassandra/sidecar/routes/HealthService.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.cassandra.sidecar.routes; - -import javax.ws.rs.GET; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; - -import com.google.common.collect.ImmutableMap; - -import com.google.inject.Singleton; -import io.netty.handler.codec.http.HttpResponseStatus; -import io.swagger.v3.oas.annotations.Operation; -import io.vertx.core.json.Json; - -/** - * Provides a simple REST endpoint to determine if Sidecar is available - */ -@Singleton -@Path("/api/v1/__health") -public class HealthService -{ - @Operation(summary = "Health Check for Sidecar's status", - description = "Returns HTTP 200 if Sidecar is available") - @Produces(MediaType.APPLICATION_JSON) - @GET - public Response sidecarHealth() - { - return Response.status(HttpResponseStatus.OK.code()).entity(Json.encode(ImmutableMap.of("status", "OK"))) - .build(); - } -} diff --git a/src/main/java/org/apache/cassandra/sidecar/routes/SwaggerOpenApiResource.java b/src/main/java/org/apache/cassandra/sidecar/routes/SwaggerOpenApiResource.java index 430b69f..71b4d13 100644 --- a/src/main/java/org/apache/cassandra/sidecar/routes/SwaggerOpenApiResource.java +++ b/src/main/java/org/apache/cassandra/sidecar/routes/SwaggerOpenApiResource.java @@ -19,7 +19,6 @@ package org.apache.cassandra.sidecar.routes; import java.util.Collections; -import java.util.HashSet; import javax.servlet.ServletConfig; import javax.ws.rs.GET; import javax.ws.rs.Path; @@ -71,6 +70,6 @@ public class SwaggerOpenApiResource static { Reader reader = new Reader(new SwaggerConfiguration()); - OAS = reader.read(new HashSet<>(Collections.singletonList(HealthService.class))); + OAS = reader.read(Collections.emptySet()); } } diff --git a/src/main/java/org/apache/cassandra/sidecar/utils/InstanceMetadataFetcher.java b/src/main/java/org/apache/cassandra/sidecar/utils/InstanceMetadataFetcher.java index 1d7d69c..f8661e5 100644 --- a/src/main/java/org/apache/cassandra/sidecar/utils/InstanceMetadataFetcher.java +++ b/src/main/java/org/apache/cassandra/sidecar/utils/InstanceMetadataFetcher.java @@ -25,8 +25,6 @@ import org.apache.cassandra.sidecar.cluster.instance.InstanceMetadata; import org.apache.cassandra.sidecar.common.CassandraAdapterDelegate; import org.jetbrains.annotations.Nullable; -import static org.apache.cassandra.sidecar.routes.AbstractHandler.extractHostAddressWithoutPort; - /** * Helper class to retrieve instance information from an instanceId or hostname. */ @@ -53,7 +51,7 @@ public class InstanceMetadataFetcher { return host == null ? firstInstance() - : instancesConfig.instanceFromHost(extractHostAddressWithoutPort(host)); + : instancesConfig.instanceFromHost(host); } /** diff --git a/src/test/integration/org/apache/cassandra/sidecar/routes/SnapshotsHandlerIntegrationTest.java b/src/test/integration/org/apache/cassandra/sidecar/routes/SnapshotsHandlerIntegrationTest.java index 6a3bc77..ac36c3b 100644 --- a/src/test/integration/org/apache/cassandra/sidecar/routes/SnapshotsHandlerIntegrationTest.java +++ b/src/test/integration/org/apache/cassandra/sidecar/routes/SnapshotsHandlerIntegrationTest.java @@ -80,8 +80,7 @@ class SnapshotsHandlerIntegrationTest extends IntegrationTestBase TEST_KEYSPACE, table); client.put(config.getPort(), "localhost", testRoute) .expect(ResponsePredicate.SC_OK) - .send(context.succeeding(response -> context.verify(() -> - { + .send(context.succeeding(response -> context.verify(() -> { assertThat(response.statusCode()).isEqualTo(OK.code()); // creating the snapshot with the same name will return a 409 (Conflict) status code @@ -105,8 +104,7 @@ class SnapshotsHandlerIntegrationTest extends IntegrationTestBase TEST_KEYSPACE, table); client.put(config.getPort(), "localhost", testRoute) .expect(ResponsePredicate.SC_OK) - .send(context.succeeding(response -> context.verify(() -> - { + .send(context.succeeding(response -> context.verify(() -> { assertThat(response.statusCode()).isEqualTo(OK.code()); // validate that the snapshot is created @@ -175,29 +173,25 @@ class SnapshotsHandlerIntegrationTest extends IntegrationTestBase // first create the snapshot client.put(config.getPort(), "localhost", testRoute) - .expect(ResponsePredicate.SC_OK) - .send(context.succeeding(createResponse -> context.verify(() -> - { + .send(context.succeeding(createResponse -> context.verify(() -> { assertThat(createResponse.statusCode()).isEqualTo(OK.code()); ExtendedCassandraContainer container = cassandraTestContext.container; - final String directory = container.execInContainer("find", - "/opt/cassandra/data/", - "-name", - "my-snapshot").getStdout().trim(); + String directory = container.execInContainer("find", + "/opt/cassandra/data/", + "-name", + "my-snapshot").getStdout().trim(); // snapshot directory exists inside container assertThat(directory).isNotBlank(); // then delete the snapshot client.delete(config.getPort(), "localhost", testRoute) - .expect(ResponsePredicate.SC_OK) - .send(context.succeeding(deleteResponse -> context.verify(() -> - { + .send(context.succeeding(deleteResponse -> context.verify(() -> { assertThat(deleteResponse.statusCode()).isEqualTo(OK.code()); // validate that the snapshot is removed - final String removedDir = container.execInContainer("find", - "/opt/cassandra/data/", - "-name", - "my-snapshot").getStdout().trim(); + String removedDir = container.execInContainer("find", + "/opt/cassandra/data/", + "-name", + "my-snapshot").getStdout().trim(); assertThat(removedDir).isEmpty(); context.completeNow(); diff --git a/src/test/java/org/apache/cassandra/sidecar/AbstractHealthServiceTest.java b/src/test/java/org/apache/cassandra/sidecar/AbstractHealthServiceTest.java index 47e47ed..ba01bc9 100644 --- a/src/test/java/org/apache/cassandra/sidecar/AbstractHealthServiceTest.java +++ b/src/test/java/org/apache/cassandra/sidecar/AbstractHealthServiceTest.java @@ -40,6 +40,7 @@ import io.vertx.ext.web.client.WebClientOptions; import io.vertx.ext.web.codec.BodyCodec; import io.vertx.junit5.VertxTestContext; +import static io.netty.handler.codec.http.HttpResponseStatus.NOT_FOUND; import static io.netty.handler.codec.http.HttpResponseStatus.OK; import static io.netty.handler.codec.http.HttpResponseStatus.SERVICE_UNAVAILABLE; import static org.assertj.core.api.Assertions.assertThat; @@ -51,7 +52,6 @@ public abstract class AbstractHealthServiceTest { private static final Logger logger = LoggerFactory.getLogger(AbstractHealthServiceTest.class); private Vertx vertx; - private Configuration config; private HttpServer server; public abstract boolean isSslEnabled(); @@ -70,10 +70,9 @@ public abstract class AbstractHealthServiceTest Injector injector = Guice.createInjector(Modules.override(new MainModule()).with(testModule())); server = injector.getInstance(HttpServer.class); vertx = injector.getInstance(Vertx.class); - config = injector.getInstance(Configuration.class); VertxTestContext context = new VertxTestContext(); - server.listen(config.getPort(), config.getHost(), context.succeedingThenComplete()); + server.listen(0, context.succeedingThenComplete()); context.awaitCompletion(5, TimeUnit.SECONDS); } @@ -92,11 +91,11 @@ public abstract class AbstractHealthServiceTest @DisplayName("Should return HTTP 200 OK if sidecar server is running") @Test - public void testSidecarHealthCheckReturnsOK(VertxTestContext testContext) + void testSidecarHealthCheckReturnsOK(VertxTestContext testContext) { WebClient client = client(); - client.get(config.getPort(), "localhost", "/api/v1/__health") + client.get(server.actualPort(), "localhost", "/api/v1/__health") .as(BodyCodec.string()) .ssl(isSslEnabled()) .send(testContext.succeeding(response -> testContext.verify(() -> @@ -125,11 +124,11 @@ public abstract class AbstractHealthServiceTest @DisplayName("Should return HTTP 200 OK when cassandra instance is up") @Test - public void testHealthCheckReturns200OK(VertxTestContext testContext) + void testHealthCheckReturns200OK(VertxTestContext testContext) { WebClient client = client(); - client.get(config.getPort(), "localhost", "/api/v1/cassandra/__health") + client.get(server.actualPort(), "localhost", "/api/v1/cassandra/__health") .as(BodyCodec.string()) .ssl(isSslEnabled()) .send(testContext.succeeding(response -> testContext.verify(() -> @@ -140,13 +139,13 @@ public abstract class AbstractHealthServiceTest }))); } - @DisplayName("Should return HTTP 503 Failure when instance is down") + @DisplayName("Should return HTTP 503 Failure when instance is down with query param") @Test - public void testHealthCheckReturns503Failure(VertxTestContext testContext) + void testHealthCheckReturns503FailureWithQueryParam(VertxTestContext testContext) { WebClient client = client(); - client.get(config.getPort(), "localhost", "/api/v1/cassandra/instance/2/__health") + client.get(server.actualPort(), "localhost", "/api/v1/cassandra/__health?instanceId=2") .as(BodyCodec.string()) .ssl(isSslEnabled()) .send(testContext.succeeding(response -> testContext.verify(() -> @@ -157,19 +156,21 @@ public abstract class AbstractHealthServiceTest }))); } - @DisplayName("Should return HTTP 503 Failure when instance is down with query param") + @DisplayName("Should return HTTP 404 (NOT FOUND) when instance is not found") @Test - public void testHealthCheckReturns503FailureWithQueryParam(VertxTestContext testContext) + void testHealthCheckReturns404NotFound(VertxTestContext testContext) { WebClient client = client(); - client.get(config.getPort(), "localhost", "/api/v1/cassandra/__health?instanceId=2") + // instance with ID=400 does not exist + client.get(server.actualPort(), "localhost", "/api/v1/cassandra/__health?instanceId=400") .as(BodyCodec.string()) .ssl(isSslEnabled()) .send(testContext.succeeding(response -> testContext.verify(() -> { - assertThat(response.statusCode()).isEqualTo(SERVICE_UNAVAILABLE.code()); - assertThat(response.body()).isEqualTo("{\"status\":\"NOT_OK\"}"); + assertThat(response.statusCode()).isEqualTo(NOT_FOUND.code()); + assertThat(response.body()) + .isEqualTo("{\"status\":\"Not Found\",\"code\":404,\"message\":\"Instance id 400 not found\"}"); testContext.completeNow(); }))); } --------------------------------------------------------------------- To unsubscribe, e-mail: commits-unsubscr...@cassandra.apache.org For additional commands, e-mail: commits-h...@cassandra.apache.org