diff --git a/modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/ElasticsearchContainer.java b/modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/ElasticsearchContainer.java index 2080d21649a..e08db06581e 100644 --- a/modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/ElasticsearchContainer.java +++ b/modules/elasticsearch/src/main/java/org/testcontainers/elasticsearch/ElasticsearchContainer.java @@ -6,6 +6,8 @@ import org.apache.commons.lang3.StringUtils; import org.testcontainers.containers.BindMode; import org.testcontainers.containers.GenericContainer; +import org.testcontainers.containers.wait.strategy.AbstractWaitStrategy; +import org.testcontainers.containers.wait.strategy.HttpWaitStrategy; import org.testcontainers.containers.wait.strategy.Wait; import org.testcontainers.utility.ComparableVersion; import org.testcontainers.utility.DockerImageName; @@ -15,6 +17,8 @@ import java.security.KeyStore; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; +import java.time.Duration; +import java.time.Instant; import java.util.Optional; import javax.net.ssl.SSLContext; @@ -75,6 +79,8 @@ public class ElasticsearchContainer extends GenericContainer { + return body.contains("\"status\":\"green\"") || body.contains("\"status\":\"yellow\""); + }) + .withStartupTimeout(remaining.isNegative() ? Duration.ZERO : remaining) + .waitUntilReady(waitStrategyTarget); + } + } + .withStartupTimeout(healthCheckTimeout) + ); + } + public String getHttpHostAddress() { return getHost() + ":" + getMappedPort(ELASTICSEARCH_DEFAULT_PORT); } /** - * Checks env first if this implies HTTP/HTTPS. - * Otherwise, detects the scheme used by Elasticsearch using curl + * Detects the HTTP scheme used by Elasticsearch. Respects explicit env-var config first; + * when ambiguous, probes the live socket with curl (requires a running container on port 9200). * * @return "http" or "https" */ diff --git a/modules/elasticsearch/src/test/java/org/testcontainers/elasticsearch/ElasticsearchContainerTest.java b/modules/elasticsearch/src/test/java/org/testcontainers/elasticsearch/ElasticsearchContainerTest.java index 52cd78b4a34..00494948f1d 100644 --- a/modules/elasticsearch/src/test/java/org/testcontainers/elasticsearch/ElasticsearchContainerTest.java +++ b/modules/elasticsearch/src/test/java/org/testcontainers/elasticsearch/ElasticsearchContainerTest.java @@ -45,6 +45,10 @@ class ElasticsearchContainerTest { .parse("docker.elastic.co/elasticsearch/elasticsearch") .withTag(ELASTICSEARCH_VERSION); + private static final DockerImageName ELASTICSEARCH_LATEST_IMAGE = DockerImageName.parse( + "docker.elastic.co/elasticsearch/elasticsearch:9.2.4" + ); + /** * Elasticsearch default username, when secured */ @@ -162,6 +166,23 @@ void elasticsearchVersion83() throws IOException { } } + @Test + void clusterHealthIsAtLeastYellowAfterStart() throws IOException { + try (ElasticsearchContainer container = new ElasticsearchContainer(ELASTICSEARCH_LATEST_IMAGE)) { + container.start(); + + Response response = getClient(container).performRequest(new Request("GET", "/_cluster/health")); + assertThat(response.getStatusLine().getStatusCode()).isEqualTo(200); + String body = EntityUtils.toString(response.getEntity()); + assertThat(body) + .as("Cluster health status should be at least yellow after container start") + .satisfiesAnyOf( + b -> assertThat(b).contains("\"status\":\"yellow\""), + b -> assertThat(b).contains("\"status\":\"green\"") + ); + } + } + @Test void elasticsearchOssImage() throws IOException { try (