From 42f9e0d37a004227b57dc38a4648521d1f7a20db Mon Sep 17 00:00:00 2001 From: Sylvain Wallez Date: Tue, 30 Aug 2022 10:39:38 +0200 Subject: [PATCH] Update to latest API spec, update ES test server to use SSL (#384) --- java-client/build.gradle.kts | 4 +- .../ElasticsearchTestServer.java | 53 ++++++++++-- .../spec_issues/SpecIssuesTest.java | 84 ++++++++++++++++++- 3 files changed, 132 insertions(+), 9 deletions(-) diff --git a/java-client/build.gradle.kts b/java-client/build.gradle.kts index 581475ae4..d9e208c0f 100644 --- a/java-client/build.gradle.kts +++ b/java-client/build.gradle.kts @@ -225,8 +225,8 @@ dependencies { // MIT // https://www.testcontainers.org/ - testImplementation("org.testcontainers", "testcontainers", "1.17.2") - testImplementation("org.testcontainers", "elasticsearch", "1.17.2") + testImplementation("org.testcontainers", "testcontainers", "1.17.3") + testImplementation("org.testcontainers", "elasticsearch", "1.17.3") } diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java index 7ae2ea10e..11fb58f60 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/ElasticsearchTestServer.java @@ -26,6 +26,7 @@ import co.elastic.clients.json.jsonb.JsonbJsonpMapper; import co.elastic.clients.transport.ElasticsearchTransport; import co.elastic.clients.transport.JsonEndpoint; +import co.elastic.clients.transport.Version; import co.elastic.clients.transport.endpoints.DelegatingJsonEndpoint; import co.elastic.clients.transport.rest_client.RestClientTransport; import org.apache.http.HttpHost; @@ -34,12 +35,16 @@ import org.apache.http.impl.client.BasicCredentialsProvider; import org.elasticsearch.client.RestClient; import org.testcontainers.elasticsearch.ElasticsearchContainer; +import org.testcontainers.images.builder.ImageFromDockerfile; +import org.testcontainers.utility.DockerImageName; +import javax.net.ssl.SSLContext; import java.io.IOException; import java.time.Duration; public class ElasticsearchTestServer implements AutoCloseable { + private final String[] plugins; private volatile ElasticsearchContainer container; private int port; private final JsonpMapper mapper = new JsonbJsonpMapper(); @@ -54,7 +59,7 @@ public static synchronized ElasticsearchTestServer global() { System.out.println("Starting global ES test server."); global = new ElasticsearchTestServer(); try { - global.setup(); + global.start(); } catch (Exception e) { e.printStackTrace(); throw e; @@ -67,24 +72,62 @@ public static synchronized ElasticsearchTestServer global() { return global; } - private synchronized void setup() { - container = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:7.17.4") + public ElasticsearchTestServer(String... plugins) { + this.plugins = plugins; + } + + public synchronized ElasticsearchTestServer start() { + Version version = Version.VERSION.major() < 8 ? new Version(7,17,5,false) : new Version(8,3,3,false); + + // Note we could use version.major() + "." + version.minor() + "-SNAPSHOT" but plugins won't install on a snapshot version + String esImage = "docker.elastic.co/elasticsearch/elasticsearch:" + version; + + DockerImageName image; + if (plugins.length == 0) { + image = DockerImageName.parse(esImage); + } else { + String esWithPluginsImage = new ImageFromDockerfile() + .withDockerfileFromBuilder(b -> { + b.from(esImage); + for (String plugin : plugins) { + b.run("/usr/share/elasticsearch/bin/elasticsearch-plugin", "install", plugin); + } + } + ).get(); + + image = DockerImageName + .parse(esWithPluginsImage) + .asCompatibleSubstituteFor("docker.elastic.co/elasticsearch/elasticsearch"); + } + + container = new ElasticsearchContainer(image) .withEnv("ES_JAVA_OPTS", "-Xms256m -Xmx256m") .withEnv("path.repo", "/tmp") // for snapshots .withStartupTimeout(Duration.ofSeconds(60)) .withPassword("changeme"); container.start(); + port = container.getMappedPort(9200); + boolean useTLS = version.major() >= 8; + HttpHost host = new HttpHost("localhost", port, useTLS ? "https": "http"); + + SSLContext sslContext = useTLS ? container.createSslContextFromCa() : null; + BasicCredentialsProvider credsProv = new BasicCredentialsProvider(); credsProv.setCredentials( AuthScope.ANY, new UsernamePasswordCredentials("elastic", "changeme") ); - restClient = RestClient.builder(new HttpHost("localhost", port)) - .setHttpClientConfigCallback(hc -> hc.setDefaultCredentialsProvider(credsProv)) + restClient = RestClient.builder(host) + .setHttpClientConfigCallback(hc -> hc + .setDefaultCredentialsProvider(credsProv) + .setSSLContext(sslContext) + ) .build(); transport = new RestClientTransport(restClient, mapper); client = new ElasticsearchClient(transport); + + return this; } /** diff --git a/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java b/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java index 6ae3c6227..54f9727be 100644 --- a/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java +++ b/java-client/src/test/java/co/elastic/clients/elasticsearch/spec_issues/SpecIssuesTest.java @@ -19,13 +19,19 @@ package co.elastic.clients.elasticsearch.spec_issues; +import co.elastic.clients.documentation.usage.Product; import co.elastic.clients.elasticsearch.ElasticsearchClient; import co.elastic.clients.elasticsearch.ElasticsearchTestServer; import co.elastic.clients.elasticsearch._types.ErrorResponse; +import co.elastic.clients.elasticsearch._types.Script; import co.elastic.clients.elasticsearch._types.analysis.LimitTokenCountTokenFilter; +import co.elastic.clients.elasticsearch._types.mapping.Property; +import co.elastic.clients.elasticsearch._types.mapping.RuntimeField; +import co.elastic.clients.elasticsearch._types.mapping.RuntimeFieldType; import co.elastic.clients.elasticsearch.cluster.ClusterStatsResponse; import co.elastic.clients.elasticsearch.core.SearchRequest; import co.elastic.clients.elasticsearch.core.SearchResponse; +import co.elastic.clients.elasticsearch.core.search.Suggester; import co.elastic.clients.elasticsearch.indices.CreateIndexRequest; import co.elastic.clients.elasticsearch.indices.GetFieldMappingRequest; import co.elastic.clients.elasticsearch.indices.GetFieldMappingResponse; @@ -75,11 +81,40 @@ public void i0201_restoreResponse() throws Exception { RestoreResponse restoreResponse = fromJson("{\"acknowledged\":true}", RestoreResponse.class); } + @Test + public void i0298_runtimeMappings() throws Exception { + ElasticsearchClient client = ElasticsearchTestServer.global().client(); + + String index = "i0298"; + + Product p = new Product("p1", "p2", 42.0); + + client.index(ir -> ir + .index(index) + .document(p)); + + client.indices().flush(f -> f.index(index)); + + RuntimeField runtimeField = RuntimeField.of(rf -> rf + .type(RuntimeFieldType.Double) + .script(Script.of(s -> s + .inline(i -> i. + source("emit(doc['price'].value * 1.19)") + ) + )) + ); + + client.search(sr -> sr + .index(index) + .runtimeMappings("priceWithTax", runtimeField), // NOTE: the builder accepts only lists here + Product.class); + } + @Test public void i0297_mappingSettings() { CreateIndexRequest request = CreateIndexRequest.of(r -> r - .index("name") + .index("i0297") .settings(s -> s // This is "mapping" and not "mappings" .mapping(m -> m.totalFields(totalFields -> totalFields.limit(1001))) @@ -118,11 +153,56 @@ public void i0295_mappingSettings() { "}"; CreateIndexRequest request = CreateIndexRequest.of(r -> r - .index("name") + .index("i0295") .withJson(new StringReader(json)) ); } + @Test + public void i0254_suggesterTest() throws Exception { + new Suggester.Builder().suggesters("song-suggest", s -> s.completion(c->c.field("suggest"))).build(); + } + + @Test + public void i0249_variantKind() throws Exception { + try (ElasticsearchTestServer server = new ElasticsearchTestServer("analysis-icu").start()) { + + ElasticsearchClient esClient = server.client(); + + esClient.indices().create(r -> r + .index("i0249") + .withJson(new StringReader("{\n" + + " \"mappings\": {\n" + + " \"properties\": {\n" + + " \"name\": { \n" + + " \"type\": \"text\",\n" + + " \"fields\": {\n" + + " \"sort\": { \n" + + " \"type\": \"icu_collation_keyword\",\n" + + " \"index\": false,\n" + + " \"language\": \"de\",\n" + + " \"country\": \"DE\",\n" + + " \"variant\": \"@collation=phonebook\"\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + " }\n" + + "}\n")) + ); + + GetFieldMappingResponse fm = esClient.indices().getFieldMapping(b -> b + .index("i0249") + .fields("*") + ); + + Property property = fm.get("i0249").mappings().get("name").mapping().get("name").text().fields().get("sort"); + + assertTrue(property._isCustom()); + assertEquals("icu_collation_keyword", property._customKind()); + } + } + @Test public void i0199_consumeAllTokensOptional() { // https://github.com/elastic/elasticsearch-java/issues/199