From d22a946fa736f4b08b9e0ec655afff4c5446c4d4 Mon Sep 17 00:00:00 2001 From: Nhat Nguyen Date: Sun, 24 Nov 2024 17:39:20 -0800 Subject: [PATCH 01/34] Fix testCancelRequestWhenFailingFetchingPages (#117437) Each data-node request involves two exchange sinks: an external one for fetching pages from the coordinator and an internal one for node-level reduction. Currently, the test selects one of these sinks randomly, leading to assertion failures. This update ensures the test consistently selects the external exchange sink. Closes #117397 --- muted-tests.yml | 3 --- .../xpack/esql/action/EsqlActionTaskIT.java | 24 +++++++++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/muted-tests.yml b/muted-tests.yml index f33ca972b7d36..0d2e6b991a5c3 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -229,9 +229,6 @@ tests: - class: org.elasticsearch.xpack.inference.DefaultEndPointsIT method: testInferDeploysDefaultElser issue: https://github.com/elastic/elasticsearch/issues/114913 -- class: org.elasticsearch.xpack.esql.action.EsqlActionTaskIT - method: testCancelRequestWhenFailingFetchingPages - issue: https://github.com/elastic/elasticsearch/issues/117397 - class: org.elasticsearch.xpack.security.operator.OperatorPrivilegesIT method: testEveryActionIsEitherOperatorOnlyOrNonOperator issue: https://github.com/elastic/elasticsearch/issues/102992 diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlActionTaskIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlActionTaskIT.java index 460ab0f5b8b38..56453a291ea81 100644 --- a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlActionTaskIT.java +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/action/EsqlActionTaskIT.java @@ -392,12 +392,13 @@ protected void doRun() throws Exception { .get(); ensureYellowAndNoInitializingShards("test"); request.query("FROM test | LIMIT 10"); - request.pragmas(randomPragmas()); + QueryPragmas pragmas = randomPragmas(); + request.pragmas(pragmas); PlainActionFuture future = new PlainActionFuture<>(); client.execute(EsqlQueryAction.INSTANCE, request, future); ExchangeService exchangeService = internalCluster().getInstance(ExchangeService.class, dataNode); - boolean waitedForPages; - final String sessionId; + final boolean waitedForPages; + final String exchangeId; try { List foundTasks = new ArrayList<>(); assertBusy(() -> { @@ -411,13 +412,22 @@ protected void doRun() throws Exception { assertThat(tasks, hasSize(1)); foundTasks.addAll(tasks); }); - sessionId = foundTasks.get(0).taskId().toString(); + final String sessionId = foundTasks.get(0).taskId().toString(); assertTrue(fetchingStarted.await(1, TimeUnit.MINUTES)); - String exchangeId = exchangeService.sinkKeys().stream().filter(s -> s.startsWith(sessionId)).findFirst().get(); + List sinkKeys = exchangeService.sinkKeys() + .stream() + .filter( + s -> s.startsWith(sessionId) + // exclude the node-level reduction sink + && s.endsWith("[n]") == false + ) + .toList(); + assertThat(sinkKeys.toString(), sinkKeys.size(), equalTo(1)); + exchangeId = sinkKeys.get(0); ExchangeSinkHandler exchangeSink = exchangeService.getSinkHandler(exchangeId); waitedForPages = randomBoolean(); if (waitedForPages) { - // do not fail exchange requests until we have some pages + // do not fail exchange requests until we have some pages. assertBusy(() -> assertThat(exchangeSink.bufferSize(), greaterThan(0))); } } finally { @@ -429,7 +439,7 @@ protected void doRun() throws Exception { // As a result, the exchange sinks on data-nodes won't be removed until the inactive_timeout elapses, which is // longer than the assertBusy timeout. if (waitedForPages == false) { - exchangeService.finishSinkHandler(sessionId, failure); + exchangeService.finishSinkHandler(exchangeId, failure); } } finally { transportService.clearAllRules(); From 2f8bb0b23ce6070335fb750d9e76265f558ea3a9 Mon Sep 17 00:00:00 2001 From: Quentin Pradet Date: Mon, 25 Nov 2024 11:43:36 +0400 Subject: [PATCH 02/34] Add missing async_search query parameters to rest-api-spec (#117312) --- docs/changelog/117312.yaml | 5 +++++ .../rest-api-spec/api/async_search.submit.json | 15 +++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 docs/changelog/117312.yaml diff --git a/docs/changelog/117312.yaml b/docs/changelog/117312.yaml new file mode 100644 index 0000000000000..302b91388ef2b --- /dev/null +++ b/docs/changelog/117312.yaml @@ -0,0 +1,5 @@ +pr: 117312 +summary: Add missing `async_search` query parameters to rest-api-spec +area: Search +type: bug +issues: [] diff --git a/rest-api-spec/src/main/resources/rest-api-spec/api/async_search.submit.json b/rest-api-spec/src/main/resources/rest-api-spec/api/async_search.submit.json index 5cd2b0e26459e..a7a7ebe838eab 100644 --- a/rest-api-spec/src/main/resources/rest-api-spec/api/async_search.submit.json +++ b/rest-api-spec/src/main/resources/rest-api-spec/api/async_search.submit.json @@ -65,6 +65,11 @@ "type":"boolean", "description":"Specify whether wildcard and prefix queries should be analyzed (default: false)" }, + "ccs_minimize_roundtrips":{ + "type":"boolean", + "default":false, + "description":"When doing a cross-cluster search, setting it to true may improve overall search latency, particularly when searching clusters with a large number of shards. However, when set to true, the progress of searches on the remote clusters will not be received until the search finishes on all clusters." + }, "default_operator":{ "type":"enum", "options":[ @@ -126,6 +131,16 @@ "type":"string", "description":"Specify the node or shard the operation should be performed on (default: random)" }, + "pre_filter_shard_size":{ + "type":"number", + "default": 1, + "description":"Cannot be changed: this is to enforce the execution of a pre-filter roundtrip to retrieve statistics from each shard so that the ones that surely don’t hold any document matching the query get skipped." + }, + "rest_total_hits_as_int":{ + "type":"boolean", + "description":"Indicates whether hits.total should be rendered as an integer or an object in the rest search response", + "default":false + }, "q":{ "type":"string", "description":"Query in the Lucene query string syntax" From b0c49766f6a2301f8938629bfdadf76459329b8d Mon Sep 17 00:00:00 2001 From: David Turner Date: Mon, 25 Nov 2024 08:01:21 +0000 Subject: [PATCH 03/34] Extract IMDS test fixture from S3 fixture (#117324) The S3 and IMDS services are separate things in practice, we shouldn't be conflating them as we do today. This commit introduces a new independent test fixture just for the IMDS endpoint and migrates the relevant tests to use it. Relates ES-9984 --- modules/repository-s3/build.gradle | 1 + .../s3/RepositoryS3ClientYamlTestSuiteIT.java | 42 +++- .../RepositoryS3EcsClientYamlTestSuiteIT.java | 30 ++- settings.gradle | 1 + test/fixtures/ec2-imds-fixture/build.gradle | 19 ++ .../fixture/aws/imds/Ec2ImdsHttpFixture.java | 66 ++++++ .../fixture/aws/imds/Ec2ImdsHttpHandler.java | 98 +++++++++ .../aws/imds/Ec2ImdsHttpHandlerTests.java | 188 ++++++++++++++++++ .../java/fixture/s3/S3HttpFixtureWithEC2.java | 84 -------- .../java/fixture/s3/S3HttpFixtureWithECS.java | 48 ----- .../s3/S3HttpFixtureWithSessionToken.java | 12 +- 11 files changed, 433 insertions(+), 156 deletions(-) create mode 100644 test/fixtures/ec2-imds-fixture/build.gradle create mode 100644 test/fixtures/ec2-imds-fixture/src/main/java/fixture/aws/imds/Ec2ImdsHttpFixture.java create mode 100644 test/fixtures/ec2-imds-fixture/src/main/java/fixture/aws/imds/Ec2ImdsHttpHandler.java create mode 100644 test/fixtures/ec2-imds-fixture/src/test/java/fixture/aws/imds/Ec2ImdsHttpHandlerTests.java delete mode 100644 test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixtureWithEC2.java delete mode 100644 test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixtureWithECS.java diff --git a/modules/repository-s3/build.gradle b/modules/repository-s3/build.gradle index 1301d17606d63..9a7f0a5994d73 100644 --- a/modules/repository-s3/build.gradle +++ b/modules/repository-s3/build.gradle @@ -45,6 +45,7 @@ dependencies { testImplementation project(':test:fixtures:s3-fixture') yamlRestTestImplementation project(":test:framework") yamlRestTestImplementation project(':test:fixtures:s3-fixture') + yamlRestTestImplementation project(':test:fixtures:ec2-imds-fixture') yamlRestTestImplementation project(':test:fixtures:minio-fixture') internalClusterTestImplementation project(':test:fixtures:minio-fixture') diff --git a/modules/repository-s3/src/yamlRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3ClientYamlTestSuiteIT.java b/modules/repository-s3/src/yamlRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3ClientYamlTestSuiteIT.java index 0ae8af0989fa6..64cb3c3fd3a69 100644 --- a/modules/repository-s3/src/yamlRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3ClientYamlTestSuiteIT.java +++ b/modules/repository-s3/src/yamlRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3ClientYamlTestSuiteIT.java @@ -9,8 +9,8 @@ package org.elasticsearch.repositories.s3; +import fixture.aws.imds.Ec2ImdsHttpFixture; import fixture.s3.S3HttpFixture; -import fixture.s3.S3HttpFixtureWithEC2; import fixture.s3.S3HttpFixtureWithSessionToken; import com.carrotsearch.randomizedtesting.annotations.Name; @@ -18,6 +18,7 @@ import com.carrotsearch.randomizedtesting.annotations.ThreadLeakFilters; import com.carrotsearch.randomizedtesting.annotations.ThreadLeakScope; +import org.elasticsearch.cluster.routing.Murmur3HashFunction; import org.elasticsearch.test.cluster.ElasticsearchCluster; import org.elasticsearch.test.fixtures.testcontainers.TestContainersThreadFilter; import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; @@ -25,15 +26,34 @@ import org.junit.rules.RuleChain; import org.junit.rules.TestRule; +import java.util.Set; + @ThreadLeakFilters(filters = { TestContainersThreadFilter.class }) @ThreadLeakScope(ThreadLeakScope.Scope.NONE) // https://github.com/elastic/elasticsearch/issues/102482 public class RepositoryS3ClientYamlTestSuiteIT extends AbstractRepositoryS3ClientYamlTestSuiteIT { - public static final S3HttpFixture s3Fixture = new S3HttpFixture(); - public static final S3HttpFixtureWithSessionToken s3HttpFixtureWithSessionToken = new S3HttpFixtureWithSessionToken(); - public static final S3HttpFixtureWithEC2 s3Ec2 = new S3HttpFixtureWithEC2(); + private static final String HASHED_SEED = Integer.toString(Murmur3HashFunction.hash(System.getProperty("tests.seed"))); + private static final String TEMPORARY_SESSION_TOKEN = "session_token-" + HASHED_SEED; + private static final String IMDS_ACCESS_KEY = "imds-access-key-" + HASHED_SEED; + private static final String IMDS_SESSION_TOKEN = "imds-session-token-" + HASHED_SEED; + + private static final S3HttpFixture s3Fixture = new S3HttpFixture(); + + private static final S3HttpFixtureWithSessionToken s3HttpFixtureWithSessionToken = new S3HttpFixtureWithSessionToken( + "session_token_bucket", + "session_token_base_path_integration_tests", + System.getProperty("s3TemporaryAccessKey"), + TEMPORARY_SESSION_TOKEN + ); + + private static final S3HttpFixtureWithSessionToken s3HttpFixtureWithImdsSessionToken = new S3HttpFixtureWithSessionToken( + "ec2_bucket", + "ec2_base_path", + IMDS_ACCESS_KEY, + IMDS_SESSION_TOKEN + ); - private static final String s3TemporarySessionToken = "session_token"; + private static final Ec2ImdsHttpFixture ec2ImdsHttpFixture = new Ec2ImdsHttpFixture(IMDS_ACCESS_KEY, IMDS_SESSION_TOKEN, Set.of()); public static ElasticsearchCluster cluster = ElasticsearchCluster.local() .module("repository-s3") @@ -41,15 +61,19 @@ public class RepositoryS3ClientYamlTestSuiteIT extends AbstractRepositoryS3Clien .keystore("s3.client.integration_test_permanent.secret_key", System.getProperty("s3PermanentSecretKey")) .keystore("s3.client.integration_test_temporary.access_key", System.getProperty("s3TemporaryAccessKey")) .keystore("s3.client.integration_test_temporary.secret_key", System.getProperty("s3TemporarySecretKey")) - .keystore("s3.client.integration_test_temporary.session_token", s3TemporarySessionToken) + .keystore("s3.client.integration_test_temporary.session_token", TEMPORARY_SESSION_TOKEN) .setting("s3.client.integration_test_permanent.endpoint", s3Fixture::getAddress) .setting("s3.client.integration_test_temporary.endpoint", s3HttpFixtureWithSessionToken::getAddress) - .setting("s3.client.integration_test_ec2.endpoint", s3Ec2::getAddress) - .systemProperty("com.amazonaws.sdk.ec2MetadataServiceEndpointOverride", s3Ec2::getAddress) + .setting("s3.client.integration_test_ec2.endpoint", s3HttpFixtureWithImdsSessionToken::getAddress) + .systemProperty("com.amazonaws.sdk.ec2MetadataServiceEndpointOverride", ec2ImdsHttpFixture::getAddress) .build(); @ClassRule - public static TestRule ruleChain = RuleChain.outerRule(s3Fixture).around(s3Ec2).around(s3HttpFixtureWithSessionToken).around(cluster); + public static TestRule ruleChain = RuleChain.outerRule(s3Fixture) + .around(s3HttpFixtureWithSessionToken) + .around(s3HttpFixtureWithImdsSessionToken) + .around(ec2ImdsHttpFixture) + .around(cluster); @ParametersFactory public static Iterable parameters() throws Exception { diff --git a/modules/repository-s3/src/yamlRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3EcsClientYamlTestSuiteIT.java b/modules/repository-s3/src/yamlRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3EcsClientYamlTestSuiteIT.java index fa21797540c17..a522c9b17145b 100644 --- a/modules/repository-s3/src/yamlRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3EcsClientYamlTestSuiteIT.java +++ b/modules/repository-s3/src/yamlRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3EcsClientYamlTestSuiteIT.java @@ -9,28 +9,48 @@ package org.elasticsearch.repositories.s3; -import fixture.s3.S3HttpFixtureWithECS; +import fixture.aws.imds.Ec2ImdsHttpFixture; +import fixture.s3.S3HttpFixtureWithSessionToken; import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; +import org.elasticsearch.cluster.routing.Murmur3HashFunction; import org.elasticsearch.test.cluster.ElasticsearchCluster; import org.elasticsearch.test.rest.yaml.ClientYamlTestCandidate; import org.junit.ClassRule; import org.junit.rules.RuleChain; import org.junit.rules.TestRule; +import java.util.Set; + public class RepositoryS3EcsClientYamlTestSuiteIT extends AbstractRepositoryS3ClientYamlTestSuiteIT { - private static final S3HttpFixtureWithECS s3Ecs = new S3HttpFixtureWithECS(); + + private static final String HASHED_SEED = Integer.toString(Murmur3HashFunction.hash(System.getProperty("tests.seed"))); + private static final String ECS_ACCESS_KEY = "ecs-access-key-" + HASHED_SEED; + private static final String ECS_SESSION_TOKEN = "ecs-session-token-" + HASHED_SEED; + + private static final S3HttpFixtureWithSessionToken s3Fixture = new S3HttpFixtureWithSessionToken( + "ecs_bucket", + "ecs_base_path", + ECS_ACCESS_KEY, + ECS_SESSION_TOKEN + ); + + private static final Ec2ImdsHttpFixture ec2ImdsHttpFixture = new Ec2ImdsHttpFixture( + ECS_ACCESS_KEY, + ECS_SESSION_TOKEN, + Set.of("/ecs_credentials_endpoint") + ); public static ElasticsearchCluster cluster = ElasticsearchCluster.local() .module("repository-s3") - .setting("s3.client.integration_test_ecs.endpoint", s3Ecs::getAddress) - .environment("AWS_CONTAINER_CREDENTIALS_FULL_URI", () -> (s3Ecs.getAddress() + "/ecs_credentials_endpoint")) + .setting("s3.client.integration_test_ecs.endpoint", s3Fixture::getAddress) + .environment("AWS_CONTAINER_CREDENTIALS_FULL_URI", () -> ec2ImdsHttpFixture.getAddress() + "/ecs_credentials_endpoint") .build(); @ClassRule - public static TestRule ruleChain = RuleChain.outerRule(s3Ecs).around(cluster); + public static TestRule ruleChain = RuleChain.outerRule(s3Fixture).around(ec2ImdsHttpFixture).around(cluster); @ParametersFactory public static Iterable parameters() throws Exception { diff --git a/settings.gradle b/settings.gradle index 333f8272447c2..7bf03263031f1 100644 --- a/settings.gradle +++ b/settings.gradle @@ -87,6 +87,7 @@ List projects = [ 'server', 'test:framework', 'test:fixtures:azure-fixture', + 'test:fixtures:ec2-imds-fixture', 'test:fixtures:gcs-fixture', 'test:fixtures:hdfs-fixture', 'test:fixtures:krb5kdc-fixture', diff --git a/test/fixtures/ec2-imds-fixture/build.gradle b/test/fixtures/ec2-imds-fixture/build.gradle new file mode 100644 index 0000000000000..7ad194acbb8fd --- /dev/null +++ b/test/fixtures/ec2-imds-fixture/build.gradle @@ -0,0 +1,19 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +apply plugin: 'elasticsearch.java' + +description = 'Fixture for emulating the Instance Metadata Service (IMDS) running in AWS EC2' + +dependencies { + api project(':server') + api("junit:junit:${versions.junit}") { + transitive = false + } + api project(':test:framework') +} diff --git a/test/fixtures/ec2-imds-fixture/src/main/java/fixture/aws/imds/Ec2ImdsHttpFixture.java b/test/fixtures/ec2-imds-fixture/src/main/java/fixture/aws/imds/Ec2ImdsHttpFixture.java new file mode 100644 index 0000000000000..68f46d778018c --- /dev/null +++ b/test/fixtures/ec2-imds-fixture/src/main/java/fixture/aws/imds/Ec2ImdsHttpFixture.java @@ -0,0 +1,66 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +package fixture.aws.imds; + +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; + +import org.junit.rules.ExternalResource; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.util.Objects; +import java.util.Set; + +public class Ec2ImdsHttpFixture extends ExternalResource { + + private HttpServer server; + + private final String accessKey; + private final String sessionToken; + private final Set alternativeCredentialsEndpoints; + + public Ec2ImdsHttpFixture(String accessKey, String sessionToken, Set alternativeCredentialsEndpoints) { + this.accessKey = accessKey; + this.sessionToken = sessionToken; + this.alternativeCredentialsEndpoints = alternativeCredentialsEndpoints; + } + + protected HttpHandler createHandler() { + return new Ec2ImdsHttpHandler(accessKey, sessionToken, alternativeCredentialsEndpoints); + } + + public String getAddress() { + return "http://" + server.getAddress().getHostString() + ":" + server.getAddress().getPort(); + } + + public void stop(int delay) { + server.stop(delay); + } + + protected void before() throws Throwable { + server = HttpServer.create(resolveAddress(), 0); + server.createContext("/", Objects.requireNonNull(createHandler())); + server.start(); + } + + @Override + protected void after() { + stop(0); + } + + private static InetSocketAddress resolveAddress() { + try { + return new InetSocketAddress(InetAddress.getByName("localhost"), 0); + } catch (UnknownHostException e) { + throw new RuntimeException(e); + } + } +} diff --git a/test/fixtures/ec2-imds-fixture/src/main/java/fixture/aws/imds/Ec2ImdsHttpHandler.java b/test/fixtures/ec2-imds-fixture/src/main/java/fixture/aws/imds/Ec2ImdsHttpHandler.java new file mode 100644 index 0000000000000..04e5e83bddfa9 --- /dev/null +++ b/test/fixtures/ec2-imds-fixture/src/main/java/fixture/aws/imds/Ec2ImdsHttpHandler.java @@ -0,0 +1,98 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ +package fixture.aws.imds; + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; + +import org.elasticsearch.ExceptionsHelper; +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.util.concurrent.ConcurrentCollections; +import org.elasticsearch.core.SuppressForbidden; +import org.elasticsearch.rest.RestStatus; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.time.Clock; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Collection; +import java.util.Objects; +import java.util.Set; + +import static org.elasticsearch.test.ESTestCase.randomIdentifier; + +/** + * Minimal HTTP handler that emulates the EC2 IMDS server + */ +@SuppressForbidden(reason = "this test uses a HttpServer to emulate the EC2 IMDS endpoint") +public class Ec2ImdsHttpHandler implements HttpHandler { + + private static final String IMDS_SECURITY_CREDENTIALS_PATH = "/latest/meta-data/iam/security-credentials/"; + + private final String accessKey; + private final String sessionToken; + private final Set validCredentialsEndpoints = ConcurrentCollections.newConcurrentSet(); + + public Ec2ImdsHttpHandler(String accessKey, String sessionToken, Collection alternativeCredentialsEndpoints) { + this.accessKey = Objects.requireNonNull(accessKey); + this.sessionToken = Objects.requireNonNull(sessionToken); + this.validCredentialsEndpoints.addAll(alternativeCredentialsEndpoints); + } + + @Override + public void handle(final HttpExchange exchange) throws IOException { + // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html + + try (exchange) { + final var path = exchange.getRequestURI().getPath(); + final var requestMethod = exchange.getRequestMethod(); + + if ("PUT".equals(requestMethod) && "/latest/api/token".equals(path)) { + // Reject IMDSv2 probe + exchange.sendResponseHeaders(RestStatus.METHOD_NOT_ALLOWED.getStatus(), -1); + return; + } + + if ("GET".equals(requestMethod)) { + if (path.equals(IMDS_SECURITY_CREDENTIALS_PATH)) { + final var profileName = randomIdentifier(); + validCredentialsEndpoints.add(IMDS_SECURITY_CREDENTIALS_PATH + profileName); + final byte[] response = profileName.getBytes(StandardCharsets.UTF_8); + exchange.getResponseHeaders().add("Content-Type", "text/plain"); + exchange.sendResponseHeaders(RestStatus.OK.getStatus(), response.length); + exchange.getResponseBody().write(response); + return; + } else if (validCredentialsEndpoints.contains(path)) { + final byte[] response = Strings.format( + """ + { + "AccessKeyId": "%s", + "Expiration": "%s", + "RoleArn": "%s", + "SecretAccessKey": "%s", + "Token": "%s" + }""", + accessKey, + ZonedDateTime.now(Clock.systemUTC()).plusDays(1L).format(DateTimeFormatter.ISO_DATE_TIME), + randomIdentifier(), + randomIdentifier(), + sessionToken + ).getBytes(StandardCharsets.UTF_8); + exchange.getResponseHeaders().add("Content-Type", "application/json"); + exchange.sendResponseHeaders(RestStatus.OK.getStatus(), response.length); + exchange.getResponseBody().write(response); + return; + } + } + + ExceptionsHelper.maybeDieOnAnotherThread(new AssertionError("not supported: " + requestMethod + " " + path)); + } + } +} diff --git a/test/fixtures/ec2-imds-fixture/src/test/java/fixture/aws/imds/Ec2ImdsHttpHandlerTests.java b/test/fixtures/ec2-imds-fixture/src/test/java/fixture/aws/imds/Ec2ImdsHttpHandlerTests.java new file mode 100644 index 0000000000000..5d5cbfae3fa60 --- /dev/null +++ b/test/fixtures/ec2-imds-fixture/src/test/java/fixture/aws/imds/Ec2ImdsHttpHandlerTests.java @@ -0,0 +1,188 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package fixture.aws.imds; + +import com.sun.net.httpserver.Headers; +import com.sun.net.httpserver.HttpContext; +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpPrincipal; + +import org.elasticsearch.common.Strings; +import org.elasticsearch.common.bytes.BytesArray; +import org.elasticsearch.common.bytes.BytesReference; +import org.elasticsearch.common.io.stream.BytesStreamOutput; +import org.elasticsearch.common.xcontent.XContentHelper; +import org.elasticsearch.rest.RestStatus; +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xcontent.XContentType; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.URI; +import java.util.Set; + +public class Ec2ImdsHttpHandlerTests extends ESTestCase { + + public void testImdsV1() throws IOException { + final var accessKey = randomIdentifier(); + final var sessionToken = randomIdentifier(); + + final var handler = new Ec2ImdsHttpHandler(accessKey, sessionToken, Set.of()); + + final var roleResponse = handleRequest(handler, "GET", "/latest/meta-data/iam/security-credentials/"); + assertEquals(RestStatus.OK, roleResponse.status()); + final var profileName = roleResponse.body().utf8ToString(); + assertTrue(Strings.hasText(profileName)); + + final var credentialsResponse = handleRequest(handler, "GET", "/latest/meta-data/iam/security-credentials/" + profileName); + assertEquals(RestStatus.OK, credentialsResponse.status()); + + final var responseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), credentialsResponse.body().streamInput(), false); + assertEquals(Set.of("AccessKeyId", "Expiration", "RoleArn", "SecretAccessKey", "Token"), responseMap.keySet()); + assertEquals(accessKey, responseMap.get("AccessKeyId")); + assertEquals(sessionToken, responseMap.get("Token")); + } + + public void testImdsV2Disabled() { + assertEquals( + RestStatus.METHOD_NOT_ALLOWED, + handleRequest(new Ec2ImdsHttpHandler(randomIdentifier(), randomIdentifier(), Set.of()), "PUT", "/latest/api/token").status() + ); + } + + private record TestHttpResponse(RestStatus status, BytesReference body) {} + + private static TestHttpResponse handleRequest(Ec2ImdsHttpHandler handler, String method, String uri) { + final var httpExchange = new TestHttpExchange(method, uri, BytesArray.EMPTY, TestHttpExchange.EMPTY_HEADERS); + try { + handler.handle(httpExchange); + } catch (IOException e) { + fail(e); + } + assertNotEquals(0, httpExchange.getResponseCode()); + return new TestHttpResponse(RestStatus.fromCode(httpExchange.getResponseCode()), httpExchange.getResponseBodyContents()); + } + + private static class TestHttpExchange extends HttpExchange { + + private static final Headers EMPTY_HEADERS = new Headers(); + + private final String method; + private final URI uri; + private final BytesReference requestBody; + private final Headers requestHeaders; + + private final Headers responseHeaders = new Headers(); + private final BytesStreamOutput responseBody = new BytesStreamOutput(); + private int responseCode; + + TestHttpExchange(String method, String uri, BytesReference requestBody, Headers requestHeaders) { + this.method = method; + this.uri = URI.create(uri); + this.requestBody = requestBody; + this.requestHeaders = requestHeaders; + } + + @Override + public Headers getRequestHeaders() { + return requestHeaders; + } + + @Override + public Headers getResponseHeaders() { + return responseHeaders; + } + + @Override + public URI getRequestURI() { + return uri; + } + + @Override + public String getRequestMethod() { + return method; + } + + @Override + public HttpContext getHttpContext() { + return null; + } + + @Override + public void close() {} + + @Override + public InputStream getRequestBody() { + try { + return requestBody.streamInput(); + } catch (IOException e) { + throw new AssertionError(e); + } + } + + @Override + public OutputStream getResponseBody() { + return responseBody; + } + + @Override + public void sendResponseHeaders(int rCode, long responseLength) { + this.responseCode = rCode; + } + + @Override + public InetSocketAddress getRemoteAddress() { + return null; + } + + @Override + public int getResponseCode() { + return responseCode; + } + + public BytesReference getResponseBodyContents() { + return responseBody.bytes(); + } + + @Override + public InetSocketAddress getLocalAddress() { + return null; + } + + @Override + public String getProtocol() { + return "HTTP/1.1"; + } + + @Override + public Object getAttribute(String name) { + return null; + } + + @Override + public void setAttribute(String name, Object value) { + fail("setAttribute not implemented"); + } + + @Override + public void setStreams(InputStream i, OutputStream o) { + fail("setStreams not implemented"); + } + + @Override + public HttpPrincipal getPrincipal() { + fail("getPrincipal not implemented"); + throw new UnsupportedOperationException("getPrincipal not implemented"); + } + } + +} diff --git a/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixtureWithEC2.java b/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixtureWithEC2.java deleted file mode 100644 index d7048cbea6b8a..0000000000000 --- a/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixtureWithEC2.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ -package fixture.s3; - -import com.sun.net.httpserver.HttpHandler; - -import org.elasticsearch.rest.RestStatus; - -import java.nio.charset.StandardCharsets; -import java.time.ZonedDateTime; -import java.time.format.DateTimeFormatter; -import java.util.Locale; - -public class S3HttpFixtureWithEC2 extends S3HttpFixtureWithSessionToken { - - private static final String EC2_PATH = "/latest/meta-data/iam/security-credentials/"; - private static final String EC2_PROFILE = "ec2Profile"; - - public S3HttpFixtureWithEC2() { - this(true); - } - - public S3HttpFixtureWithEC2(boolean enabled) { - this(enabled, "ec2_bucket", "ec2_base_path", "ec2_access_key", "ec2_session_token"); - } - - public S3HttpFixtureWithEC2(boolean enabled, String bucket, String basePath, String accessKey, String sessionToken) { - super(enabled, bucket, basePath, accessKey, sessionToken); - } - - @Override - protected HttpHandler createHandler() { - final HttpHandler delegate = super.createHandler(); - - return exchange -> { - final String path = exchange.getRequestURI().getPath(); - // http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/iam-roles-for-amazon-ec2.html - if ("GET".equals(exchange.getRequestMethod()) && path.startsWith(EC2_PATH)) { - if (path.equals(EC2_PATH)) { - final byte[] response = EC2_PROFILE.getBytes(StandardCharsets.UTF_8); - exchange.getResponseHeaders().add("Content-Type", "text/plain"); - exchange.sendResponseHeaders(RestStatus.OK.getStatus(), response.length); - exchange.getResponseBody().write(response); - exchange.close(); - return; - - } else if (path.equals(EC2_PATH + EC2_PROFILE)) { - final byte[] response = buildCredentialResponse(accessKey, sessionToken).getBytes(StandardCharsets.UTF_8); - exchange.getResponseHeaders().add("Content-Type", "application/json"); - exchange.sendResponseHeaders(RestStatus.OK.getStatus(), response.length); - exchange.getResponseBody().write(response); - exchange.close(); - return; - } - - final byte[] response = "unknown profile".getBytes(StandardCharsets.UTF_8); - exchange.getResponseHeaders().add("Content-Type", "text/plain"); - exchange.sendResponseHeaders(RestStatus.NOT_FOUND.getStatus(), response.length); - exchange.getResponseBody().write(response); - exchange.close(); - return; - - } - delegate.handle(exchange); - }; - } - - protected static String buildCredentialResponse(final String ec2AccessKey, final String ec2SessionToken) { - return String.format(Locale.ROOT, """ - { - "AccessKeyId": "%s", - "Expiration": "%s", - "RoleArn": "arn", - "SecretAccessKey": "secret_access_key", - "Token": "%s" - }""", ec2AccessKey, ZonedDateTime.now().plusDays(1L).format(DateTimeFormatter.ISO_DATE_TIME), ec2SessionToken); - } -} diff --git a/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixtureWithECS.java b/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixtureWithECS.java deleted file mode 100644 index d6266ea75dd3a..0000000000000 --- a/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixtureWithECS.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the "Elastic License - * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side - * Public License v 1"; you may not use this file except in compliance with, at - * your election, the "Elastic License 2.0", the "GNU Affero General Public - * License v3.0 only", or the "Server Side Public License, v 1". - */ -package fixture.s3; - -import com.sun.net.httpserver.HttpHandler; - -import org.elasticsearch.rest.RestStatus; - -import java.nio.charset.StandardCharsets; - -public class S3HttpFixtureWithECS extends S3HttpFixtureWithEC2 { - - public S3HttpFixtureWithECS() { - this(true); - } - - public S3HttpFixtureWithECS(boolean enabled) { - this(enabled, "ecs_bucket", "ecs_base_path", "ecs_access_key", "ecs_session_token"); - } - - public S3HttpFixtureWithECS(boolean enabled, String bucket, String basePath, String accessKey, String sessionToken) { - super(enabled, bucket, basePath, accessKey, sessionToken); - } - - @Override - protected HttpHandler createHandler() { - final HttpHandler delegate = super.createHandler(); - - return exchange -> { - // https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html - if ("GET".equals(exchange.getRequestMethod()) && exchange.getRequestURI().getPath().equals("/ecs_credentials_endpoint")) { - final byte[] response = buildCredentialResponse(accessKey, sessionToken).getBytes(StandardCharsets.UTF_8); - exchange.getResponseHeaders().add("Content-Type", "application/json"); - exchange.sendResponseHeaders(RestStatus.OK.getStatus(), response.length); - exchange.getResponseBody().write(response); - exchange.close(); - return; - } - delegate.handle(exchange); - }; - } -} diff --git a/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixtureWithSessionToken.java b/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixtureWithSessionToken.java index 1a1cbba651e06..001cc34d9b20d 100644 --- a/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixtureWithSessionToken.java +++ b/test/fixtures/s3-fixture/src/main/java/fixture/s3/S3HttpFixtureWithSessionToken.java @@ -18,16 +18,8 @@ public class S3HttpFixtureWithSessionToken extends S3HttpFixture { protected final String sessionToken; - public S3HttpFixtureWithSessionToken() { - this(true); - } - - public S3HttpFixtureWithSessionToken(boolean enabled) { - this(enabled, "session_token_bucket", "session_token_base_path_integration_tests", "session_token_access_key", "session_token"); - } - - public S3HttpFixtureWithSessionToken(boolean enabled, String bucket, String basePath, String accessKey, String sessionToken) { - super(enabled, bucket, basePath, accessKey); + public S3HttpFixtureWithSessionToken(String bucket, String basePath, String accessKey, String sessionToken) { + super(true, bucket, basePath, accessKey); this.sessionToken = sessionToken; } From 79d8eb51b4f87276a5c9259af46b635d42a75058 Mon Sep 17 00:00:00 2001 From: David Turner Date: Mon, 25 Nov 2024 09:30:53 +0000 Subject: [PATCH 04/34] Rename `RepositoryS3RestIT` (#117449) This test suite is less generic than its current name suggests. Relates ES-9984 --- ...stIT.java => RepositoryS3RestReloadCredentialsIT.java} | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) rename modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/{RepositoryS3RestIT.java => RepositoryS3RestReloadCredentialsIT.java} (89%) diff --git a/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3RestIT.java b/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3RestReloadCredentialsIT.java similarity index 89% rename from modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3RestIT.java rename to modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3RestReloadCredentialsIT.java index dcd29c6d26c6e..2f3e995b52468 100644 --- a/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3RestIT.java +++ b/modules/repository-s3/src/javaRestTest/java/org/elasticsearch/repositories/s3/RepositoryS3RestReloadCredentialsIT.java @@ -13,6 +13,7 @@ import org.elasticsearch.client.Request; import org.elasticsearch.client.ResponseException; +import org.elasticsearch.cluster.routing.Murmur3HashFunction; import org.elasticsearch.common.settings.Settings; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.cluster.ElasticsearchCluster; @@ -28,10 +29,11 @@ import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.equalTo; -public class RepositoryS3RestIT extends ESRestTestCase { +public class RepositoryS3RestReloadCredentialsIT extends ESRestTestCase { - private static final String BUCKET = "RepositoryS3JavaRestTest-bucket"; - private static final String BASE_PATH = "RepositoryS3JavaRestTest-base-path"; + private static final String HASHED_SEED = Integer.toString(Murmur3HashFunction.hash(System.getProperty("tests.seed"))); + private static final String BUCKET = "RepositoryS3RestReloadCredentialsIT-bucket-" + HASHED_SEED; + private static final String BASE_PATH = "RepositoryS3RestReloadCredentialsIT-base-path-" + HASHED_SEED; public static final S3HttpFixture s3Fixture = new S3HttpFixture(true, BUCKET, BASE_PATH, "ignored"); From fbc6abec0552a29b99675800ed134468910fb9f1 Mon Sep 17 00:00:00 2001 From: Kostas Krikellas <131142368+kkrik-es@users.noreply.github.com> Date: Mon, 25 Nov 2024 11:32:28 +0200 Subject: [PATCH 05/34] [TEST] Unmute randomized logsdb test (#117450) Test fixed in #117228 and here. Fixes #116536 Fixes #117212 --- muted-tests.yml | 6 ------ .../qa/StandardVersusLogsIndexModeChallengeRestIT.java | 10 +++++----- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/muted-tests.yml b/muted-tests.yml index 0d2e6b991a5c3..d4b77f5269c10 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -168,9 +168,6 @@ tests: - class: org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshotsCanMatchOnCoordinatorIntegTests method: testSearchableSnapshotShardsAreSkippedBySearchRequestWithoutQueryingAnyNodeWhenTheyAreOutsideOfTheQueryRange issue: https://github.com/elastic/elasticsearch/issues/116523 -- class: org.elasticsearch.xpack.logsdb.qa.StandardVersusLogsIndexModeRandomDataDynamicMappingChallengeRestIT - method: testMatchAllQuery - issue: https://github.com/elastic/elasticsearch/issues/116536 - class: org.elasticsearch.xpack.esql.ccq.MultiClusterSpecIT method: test {categorize.Categorize} issue: https://github.com/elastic/elasticsearch/issues/116434 @@ -208,9 +205,6 @@ tests: - class: org.elasticsearch.xpack.inference.DefaultEndPointsIT method: testMultipleInferencesTriggeringDownloadAndDeploy issue: https://github.com/elastic/elasticsearch/issues/117208 -- class: org.elasticsearch.xpack.logsdb.qa.StandardVersusLogsStoredSourceChallengeRestIT - method: testEsqlSource - issue: https://github.com/elastic/elasticsearch/issues/117212 - class: org.elasticsearch.ingest.geoip.EnterpriseGeoIpDownloaderIT method: testEnterpriseDownloaderTask issue: https://github.com/elastic/elasticsearch/issues/115163 diff --git a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeChallengeRestIT.java b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeChallengeRestIT.java index 8930ff23fb3b0..e411f2f3f314d 100644 --- a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeChallengeRestIT.java +++ b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/qa/StandardVersusLogsIndexModeChallengeRestIT.java @@ -181,7 +181,7 @@ protected static void waitForLogs(RestClient client) throws Exception { } public void testMatchAllQuery() throws IOException { - int numberOfDocuments = ESTestCase.randomIntBetween(100, 200); + int numberOfDocuments = ESTestCase.randomIntBetween(20, 100); final List documents = generateDocuments(numberOfDocuments); indexDocuments(documents); @@ -199,7 +199,7 @@ public void testMatchAllQuery() throws IOException { } public void testTermsQuery() throws IOException { - int numberOfDocuments = ESTestCase.randomIntBetween(100, 200); + int numberOfDocuments = ESTestCase.randomIntBetween(20, 100); final List documents = generateDocuments(numberOfDocuments); indexDocuments(documents); @@ -217,7 +217,7 @@ public void testTermsQuery() throws IOException { } public void testHistogramAggregation() throws IOException { - int numberOfDocuments = ESTestCase.randomIntBetween(100, 200); + int numberOfDocuments = ESTestCase.randomIntBetween(20, 100); final List documents = generateDocuments(numberOfDocuments); indexDocuments(documents); @@ -235,7 +235,7 @@ public void testHistogramAggregation() throws IOException { } public void testTermsAggregation() throws IOException { - int numberOfDocuments = ESTestCase.randomIntBetween(100, 200); + int numberOfDocuments = ESTestCase.randomIntBetween(20, 100); final List documents = generateDocuments(numberOfDocuments); indexDocuments(documents); @@ -253,7 +253,7 @@ public void testTermsAggregation() throws IOException { } public void testDateHistogramAggregation() throws IOException { - int numberOfDocuments = ESTestCase.randomIntBetween(100, 200); + int numberOfDocuments = ESTestCase.randomIntBetween(20, 100); final List documents = generateDocuments(numberOfDocuments); indexDocuments(documents); From 1d4c8d85f6641f8f4efa776106392b0eb6980406 Mon Sep 17 00:00:00 2001 From: Luke Whiting Date: Mon, 25 Nov 2024 09:51:11 +0000 Subject: [PATCH 06/34] (#34659) - Add Timezone Configuration to Watcher (#117033) * Add timezone support to Cron objects * Add timezone support to CronnableSchedule * XContent change to support parsing and display of TimeZone fields on schedules * Case insensitive timezone parsing * Doc changes * YAML REST tests * Equals, toString and HashCode now include timezone * Additional random testing for DST transitions * Migrate Cron class to use wrapped LocalDateTime The algorithm depends on some quirks of calendar but LocalDateTime correctly ignores DST during calculations so this uses a LocalDateTime with a wrapper to emulate some of Calendar's behaviours that the Cron algorithm depends on * Additional documentation to explain discontinuity event behaviour * Remove redundant conversions from ZoneId to TimeZone following move to LocalDateTime * Add documentation warning that manual clock changes will cause unpredictable watch execution * Update docs/reference/watcher/trigger/schedule.asciidoc Co-authored-by: Lee Hinman --------- Co-authored-by: Lee Hinman --- .../watching-time-series-data.asciidoc | 8 +- .../watcher/trigger/schedule.asciidoc | 33 +- .../watcher/trigger/schedule/cron.asciidoc | 42 ++- .../watcher/trigger/schedule/daily.asciidoc | 24 ++ .../watcher/trigger/schedule/monthly.asciidoc | 24 +- .../watcher/trigger/schedule/weekly.asciidoc | 24 +- .../watcher/trigger/schedule/yearly.asciidoc | 23 ++ .../xpack/core/scheduler/Cron.java | 287 +++++++++--------- .../scheduler/LocalDateTimeLegacyWrapper.java | 130 ++++++++ .../core/scheduler/CronTimezoneTests.java | 231 ++++++++++++++ .../connector/ConnectorCustomSchedule.java | 2 +- .../connector/ConnectorScheduling.java | 2 +- .../slm/SnapshotLifecyclePolicyTests.java | 4 +- .../put_watch/11_timezoned_schedules.yml | 121 ++++++++ .../trigger/schedule/CronnableSchedule.java | 34 ++- .../trigger/schedule/ScheduleRegistry.java | 40 ++- .../trigger/schedule/ScheduleTrigger.java | 9 +- .../schedule/support/TimezoneUtils.java | 55 ++++ .../schedule/ScheduleRegistryTests.java | 15 +- .../schedule/support/TimezoneUtilsTests.java | 40 +++ 20 files changed, 975 insertions(+), 173 deletions(-) create mode 100644 x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/scheduler/LocalDateTimeLegacyWrapper.java create mode 100644 x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/scheduler/CronTimezoneTests.java create mode 100644 x-pack/plugin/watcher/qa/rest/src/yamlRestTest/resources/rest-api-spec/test/watcher/put_watch/11_timezoned_schedules.yml create mode 100644 x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/support/TimezoneUtils.java create mode 100644 x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/trigger/schedule/support/TimezoneUtilsTests.java diff --git a/docs/reference/watcher/example-watches/watching-time-series-data.asciidoc b/docs/reference/watcher/example-watches/watching-time-series-data.asciidoc index 421c69619cfea..b1c776baae1de 100644 --- a/docs/reference/watcher/example-watches/watching-time-series-data.asciidoc +++ b/docs/reference/watcher/example-watches/watching-time-series-data.asciidoc @@ -62,20 +62,20 @@ contain the words "error" or "problem". To set up the watch: -. Define the watch trigger--a daily schedule that runs at 12:00 UTC: +. Define the watch trigger--a daily schedule that runs at 12:00 Australian Eastern Standard Time (UTC+10:00): + [source,js] -------------------------------------------------- "trigger" : { "schedule" : { + "timezone": "Australia/Brisbane", "daily" : { "at" : "12:00" } } } -------------------------------------------------- + -NOTE: In {watcher}, you specify times in UTC time. Don't forget to do the - conversion from your local time so the schedule triggers at the time - you intend. +NOTE: In {watcher}, if the timezone is omitted then schedules default to UTC. `timezone` can be specified either +as a +/-HH:mm offset from UTC or as a timezone name from the machines local IANA Time Zone Database. . Define the watch input--a search that uses a filter to constrain the results to the past day. diff --git a/docs/reference/watcher/trigger/schedule.asciidoc b/docs/reference/watcher/trigger/schedule.asciidoc index fa389409d15c4..d2bf466644e10 100644 --- a/docs/reference/watcher/trigger/schedule.asciidoc +++ b/docs/reference/watcher/trigger/schedule.asciidoc @@ -6,12 +6,42 @@ ++++ Schedule <> define when the watch execution should start based -on date and time. All times are specified in UTC time. +on date and time. All times are in UTC time unless a timezone is explicitly specified +in the schedule. {watcher} uses the system clock to determine the current time. To ensure schedules are triggered when expected, you should synchronize the clocks of all nodes in the cluster using a time service such as http://www.ntp.org/[NTP]. +NOTE: {watcher} can't correct for manual adjustments to the system clock. Be aware when making +such changes that watch execution may be affected with watches being skipped or repeated if the +adjustment covers their target execution time. This applies to changes made via NTP as well. + +When specifying a timezone for a watch, keep in mind the effect daylight savings time +transitions may have on the schedule, especially if the watch is scheduled to run +during the transition. Here's how {watcher} handles watches scheduled during discontinuities: + +==== Gap Transitions +These occur when the clock moves forward, such as when daylight savings time starts +and cause certain hours or minutes to be skipped. If your watch is scheduled to run +during a gap transition, the watch is executed at the same time as before the transition. + +Example: If a watch is scheduled to run daily at 1:30AM in the `Europe/London` time zone and +the clock moves forward one hour from 1:00AM (GMT+0) to 2:00AM (GMT+1), the watch is executed +at 2:30AM (GMT+1) which would have been 1:30AM before the transition. Subsequent executions +happen at 1:30AM (GMT+1). + +==== Overlap Transitions +These occur when the clock moves backward, such as when daylight savings time ends +and cause certain hours or minutes to be repeated. If your watch is scheduled to run +during an overlap transition, only the first occurrence of the time causes to the watch +to execute with the second being skipped. + +Example: If a watch is scheduled to run at 1:30 AM and the clock moves backward one hour +from 2:00AM to 1:00AM, the watch is executed at 1:30AM and the second occurrence after the +change is skipped. + +=== Throttling Keep in mind that the throttle period can affect when a watch is actually executed. The default throttle period is five seconds (5000 ms). If you configure a schedule that's more frequent than the throttle period, the throttle period overrides the @@ -20,6 +50,7 @@ and set the schedule to every 10 seconds, the watch is executed no more than once per minute. For more information about throttling, see <>. +=== Schedule Types {watcher} provides several types of schedule triggers: * <> diff --git a/docs/reference/watcher/trigger/schedule/cron.asciidoc b/docs/reference/watcher/trigger/schedule/cron.asciidoc index 673f350435c5f..c33bf524a8737 100644 --- a/docs/reference/watcher/trigger/schedule/cron.asciidoc +++ b/docs/reference/watcher/trigger/schedule/cron.asciidoc @@ -5,14 +5,14 @@ ++++ -Defines a <> using a <> +Defines a <> using a <> that specifiues when to execute a watch. -TIP: While cron expressions are powerful, a regularly occurring schedule -is easier to configure with the other schedule types. -If you must use a cron schedule, make sure you verify it with -<> . +TIP: While cron expressions are powerful, a regularly occurring schedule +is easier to configure with the other schedule types. +If you must use a cron schedule, make sure you verify it with +<> . ===== Configure a cron schedule with one time @@ -60,16 +60,40 @@ minute during the weekend: -------------------------------------------------- // NOTCONSOLE +[[configue_cron_time-zone]] +==== Use a different time zone for a cron schedule +By default, cron expressions are evaluated in the UTC time zone. To use a different time zone, +you can specify the `timezone` parameter in the schedule. For example, the following +`cron` schedule triggers at 6:00 AM and 6:00 PM during weekends in the `America/Los_Angeles` time zone: + + +[source,js] +-------------------------------------------------- +{ + ... + "trigger" : { + "schedule" : { + "timezone" : "America/Los_Angeles", + "cron" : [ + "0 6,18 * * * SAT-SUN", + ] + } + } + ... +} +-------------------------------------------------- +// NOTCONSOLE + [[croneval]] ===== Use croneval to validate cron expressions -{es} provides a <> command line tool -in the `$ES_HOME/bin` directory that you can use to check that your cron expressions +{es} provides a <> command line tool +in the `$ES_HOME/bin` directory that you can use to check that your cron expressions are valid and produce the expected results. -To validate a cron expression, pass it in as a parameter to `elasticsearch-croneval`: +To validate a cron expression, pass it in as a parameter to `elasticsearch-croneval`: [source,bash] -------------------------------------------------- bin/elasticsearch-croneval "0 0/1 * * * ?" --------------------------------------------------- +-------------------------------------------------- diff --git a/docs/reference/watcher/trigger/schedule/daily.asciidoc b/docs/reference/watcher/trigger/schedule/daily.asciidoc index cea2b8316e02f..d258d9c612350 100644 --- a/docs/reference/watcher/trigger/schedule/daily.asciidoc +++ b/docs/reference/watcher/trigger/schedule/daily.asciidoc @@ -97,3 +97,27 @@ or minutes as an array. For example, following `daily` schedule triggers at } -------------------------------------------------- // NOTCONSOLE + +[[specifying-time-zone-for-daily-schedule]] +===== Specifying a time zone for a daily schedule +By default, daily schedules are evaluated in the UTC time zone. To use a different time zone, +you can specify the `timezone` parameter in the schedule. For example, the following +`daily` schedule triggers at 6:00 AM and 6:00 PM in the `Pacific/Galapagos` time zone: + +[source,js] +-------------------------------------------------- +{ + "trigger" : { + "schedule" : { + "timezone" : "Pacific/Galapagos", + "daily" : { + "at" : { + "hour" : [ 6, 18 ], + "minute" : 0 + } + } + } + } +} +-------------------------------------------------- +// NOTCONSOLE diff --git a/docs/reference/watcher/trigger/schedule/monthly.asciidoc b/docs/reference/watcher/trigger/schedule/monthly.asciidoc index 7d13262ed2fa8..694c76aaee23a 100644 --- a/docs/reference/watcher/trigger/schedule/monthly.asciidoc +++ b/docs/reference/watcher/trigger/schedule/monthly.asciidoc @@ -74,4 +74,26 @@ schedule triggers at 12:00 AM and 12:00 PM on the 10th and 20th of each month. } } -------------------------------------------------- -// NOTCONSOLE \ No newline at end of file +// NOTCONSOLE + +==== Configuring time zones for monthly schedules +By default, monthly schedules are evaluated in the UTC time zone. To use a different +time zone, you can specify the `timezone` parameter in the schedule. For example, +the following `monthly` schedule triggers at 6:00 AM and 6:00 PM on the 15th of each month in +the `Asia/Tokyo` time zone: + +[source,js] +-------------------------------------------------- +{ + "trigger" : { + "schedule" : { + "timezone" : "Asia/Tokyo", + "monthly" : { + "on" : [ 15 ], + "at" : [ 6:00, 18:00 ] + } + } + } +} +-------------------------------------------------- +// NOTCONSOLE diff --git a/docs/reference/watcher/trigger/schedule/weekly.asciidoc b/docs/reference/watcher/trigger/schedule/weekly.asciidoc index 5b43de019ad25..53bd2f3167b21 100644 --- a/docs/reference/watcher/trigger/schedule/weekly.asciidoc +++ b/docs/reference/watcher/trigger/schedule/weekly.asciidoc @@ -79,4 +79,26 @@ Alternatively, you can specify days and times in an object that has `on` and } } -------------------------------------------------- -// NOTCONSOLE \ No newline at end of file +// NOTCONSOLE + +==== Use a different time zone for a weekly schedule +By default, weekly schedules are evaluated in the UTC time zone. To use a different time zone, +you can specify the `timezone` parameter in the schedule. For example, the following +`weekly` schedule triggers at 6:00 AM and 6:00 PM on Tuesdays and Fridays in the +`America/Buenos_Aires` time zone: + +[source,js] +-------------------------------------------------- +{ + "trigger" : { + "schedule" : { + "timezone" : "America/Buenos_Aires", + "weekly" : { + "on" : [ "tuesday", "friday" ], + "at" : [ "6:00", "18:00" ] + } + } + } +} +-------------------------------------------------- +// NOTCONSOLE diff --git a/docs/reference/watcher/trigger/schedule/yearly.asciidoc b/docs/reference/watcher/trigger/schedule/yearly.asciidoc index 8fce024bf9f4a..c33321ef5a7dc 100644 --- a/docs/reference/watcher/trigger/schedule/yearly.asciidoc +++ b/docs/reference/watcher/trigger/schedule/yearly.asciidoc @@ -88,3 +88,26 @@ January 20th, December 10th, and December 20th. } -------------------------------------------------- // NOTCONSOLE + +==== Configuring a yearly schedule with a different time zone +By default, the `yearly` schedule is evaluated in the UTC time zone. To use a +different time zone, you can specify the `timezone` parameter in the schedule. +For example, the following `yearly` schedule triggers at 3:30 PM and 8:30 PM +on June 4th in the `Antarctica/Troll` time zone: + +[source,js] +-------------------------------------------------- +{ + "trigger" : { + "schedule" : { + "timezone" : "Antarctica/Troll", + "yearly" : { + "in" : "june", + "on" : 4, + "at" : [ 15:30, 20:30 ] + } + } + } +} +-------------------------------------------------- +// NOTCONSOLE diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/scheduler/Cron.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/scheduler/Cron.java index b9d39aa665848..c94b90b6c0c23 100644 --- a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/scheduler/Cron.java +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/scheduler/Cron.java @@ -8,11 +8,15 @@ import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.common.time.DateFormatter; +import org.elasticsearch.core.SuppressForbidden; import org.elasticsearch.xcontent.ToXContentFragment; import org.elasticsearch.xcontent.XContentBuilder; import java.io.IOException; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.ZoneOffset; +import java.time.temporal.ChronoField; import java.util.Calendar; import java.util.Iterator; import java.util.Locale; @@ -232,6 +236,8 @@ public class Cron implements ToXContentFragment { private final String expression; + private ZoneId timeZone; + private transient TreeSet seconds; private transient TreeSet minutes; private transient TreeSet hours; @@ -246,7 +252,20 @@ public class Cron implements ToXContentFragment { private transient boolean nearestWeekday = false; private transient int lastdayOffset = 0; - public static final int MAX_YEAR = Calendar.getInstance(UTC, Locale.ROOT).get(Calendar.YEAR) + 100; + // Restricted to 50 years as the tzdb only has correct DST transition information for countries using a lunar calendar + // for the next ~60 years + public static final int MAX_YEAR = Calendar.getInstance(UTC, Locale.ROOT).get(Calendar.YEAR) + 50; + + public Cron(String expression, ZoneId timeZone) { + this.timeZone = timeZone; + assert expression != null : "cron expression cannot be null"; + this.expression = expression.toUpperCase(Locale.ROOT); + try { + buildExpression(this.expression); + } catch (Exception e) { + throw illegalArgument("invalid cron expression [{}]", e, expression); + } + } /** * Constructs a new CronExpression based on the specified @@ -259,13 +278,7 @@ public class Cron implements ToXContentFragment { * CronExpression */ public Cron(String expression) { - assert expression != null : "cron expression cannot be null"; - this.expression = expression.toUpperCase(Locale.ROOT); - try { - buildExpression(this.expression); - } catch (Exception e) { - throw illegalArgument("invalid cron expression [{}]", e, expression); - } + this(expression, UTC.toZoneId()); } /** @@ -275,7 +288,11 @@ public Cron(String expression) { * @param cron The existing cron expression to be copied */ public Cron(Cron cron) { - this(cron.expression); + this(cron.expression, cron.timeZone); + } + + public void setTimeZone(ZoneId timeZone) { + this.timeZone = timeZone; } /** @@ -286,31 +303,25 @@ public Cron(Cron cron) { * a time that is previous to the given time) * @return the next valid time (since the epoch) */ + @SuppressForbidden(reason = "In this case, the DST ambiguity of the atZone method is desired, understood and tested") public long getNextValidTimeAfter(final long time) { - // Computation is based on Gregorian year only. - Calendar cl = new java.util.GregorianCalendar(UTC, Locale.ROOT); - - // move ahead one second, since we're computing the time *after* the - // given time - final long afterTime = time + 1000; - // CronTrigger does not deal with milliseconds - cl.setTimeInMillis(afterTime); - cl.set(Calendar.MILLISECOND, 0); + LocalDateTime afterTimeLdt = LocalDateTime.ofInstant(java.time.Instant.ofEpochMilli(time), timeZone).plusSeconds(1); + LocalDateTimeLegacyWrapper cl = new LocalDateTimeLegacyWrapper(afterTimeLdt.with(ChronoField.MILLI_OF_SECOND, 0)); boolean gotOne = false; // loop until we've computed the next time, or we've past the endTime while (gotOne == false) { - if (cl.get(Calendar.YEAR) > 2999) { // prevent endless loop... + if (cl.getYear() > 2999) { // prevent endless loop... return -1; } SortedSet st = null; int t = 0; - int sec = cl.get(Calendar.SECOND); - int min = cl.get(Calendar.MINUTE); + int sec = cl.getSecond(); + int min = cl.getMinute(); // get second................................................. st = seconds.tailSet(sec); @@ -319,12 +330,12 @@ public long getNextValidTimeAfter(final long time) { } else { sec = seconds.first(); min++; - cl.set(Calendar.MINUTE, min); + cl.setMinute(min); } - cl.set(Calendar.SECOND, sec); + cl.setSecond(sec); - min = cl.get(Calendar.MINUTE); - int hr = cl.get(Calendar.HOUR_OF_DAY); + min = cl.getMinute(); + int hr = cl.getHour(); t = -1; // get minute................................................. @@ -337,15 +348,15 @@ public long getNextValidTimeAfter(final long time) { hr++; } if (min != t) { - cl.set(Calendar.SECOND, 0); - cl.set(Calendar.MINUTE, min); - setCalendarHour(cl, hr); + cl.setSecond(0); + cl.setMinute(min); + cl.setHour(hr); continue; } - cl.set(Calendar.MINUTE, min); + cl.setMinute(min); - hr = cl.get(Calendar.HOUR_OF_DAY); - int day = cl.get(Calendar.DAY_OF_MONTH); + hr = cl.getHour(); + int day = cl.getDayOfMonth(); t = -1; // get hour................................................... @@ -358,16 +369,16 @@ public long getNextValidTimeAfter(final long time) { day++; } if (hr != t) { - cl.set(Calendar.SECOND, 0); - cl.set(Calendar.MINUTE, 0); - cl.set(Calendar.DAY_OF_MONTH, day); - setCalendarHour(cl, hr); + cl.setSecond(0); + cl.setMinute(0); + cl.setDayOfMonth(day); + cl.setHour(hr); continue; } - cl.set(Calendar.HOUR_OF_DAY, hr); + cl.setHour(hr); - day = cl.get(Calendar.DAY_OF_MONTH); - int mon = cl.get(Calendar.MONTH) + 1; + day = cl.getDayOfMonth(); + int mon = cl.getMonth() + 1; // '+ 1' because calendar is 0-based for this field, and we are // 1-based t = -1; @@ -381,32 +392,32 @@ public long getNextValidTimeAfter(final long time) { if (lastdayOfMonth) { if (nearestWeekday == false) { t = day; - day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + day = getLastDayOfMonth(mon, cl.getYear()); day -= lastdayOffset; if (t > day) { mon++; if (mon > 12) { mon = 1; tmon = 3333; // ensure test of mon != tmon further below fails - cl.add(Calendar.YEAR, 1); + cl.plusYears(1); } day = 1; } } else { t = day; - day = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + day = getLastDayOfMonth(mon, cl.getYear()); day -= lastdayOffset; - Calendar tcal = Calendar.getInstance(UTC, Locale.ROOT); - tcal.set(Calendar.SECOND, 0); - tcal.set(Calendar.MINUTE, 0); - tcal.set(Calendar.HOUR_OF_DAY, 0); - tcal.set(Calendar.DAY_OF_MONTH, day); - tcal.set(Calendar.MONTH, mon - 1); - tcal.set(Calendar.YEAR, cl.get(Calendar.YEAR)); + LocalDateTimeLegacyWrapper tcal = new LocalDateTimeLegacyWrapper(LocalDateTime.now(timeZone)); + tcal.setSecond(0); + tcal.setMinute(0); + tcal.setHour(0); + tcal.setDayOfMonth(day); + tcal.setMonth(mon - 1); + tcal.setYear(cl.getYear()); - int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); - int dow = tcal.get(Calendar.DAY_OF_WEEK); + int ldom = getLastDayOfMonth(mon, cl.getYear()); + int dow = tcal.getDayOfWeek(); if (dow == Calendar.SATURDAY && day == 1) { day += 2; @@ -418,13 +429,12 @@ public long getNextValidTimeAfter(final long time) { day += 1; } - tcal.set(Calendar.SECOND, sec); - tcal.set(Calendar.MINUTE, min); - tcal.set(Calendar.HOUR_OF_DAY, hr); - tcal.set(Calendar.DAY_OF_MONTH, day); - tcal.set(Calendar.MONTH, mon - 1); - long nTime = tcal.getTimeInMillis(); - if (nTime < afterTime) { + tcal.setSecond(sec); + tcal.setMinute(min); + tcal.setHour(hr); + tcal.setDayOfMonth(day); + tcal.setMonth(mon - 1); + if (tcal.isBefore(afterTimeLdt)) { day = 1; mon++; } @@ -433,16 +443,16 @@ public long getNextValidTimeAfter(final long time) { t = day; day = daysOfMonth.first(); - Calendar tcal = Calendar.getInstance(UTC, Locale.ROOT); - tcal.set(Calendar.SECOND, 0); - tcal.set(Calendar.MINUTE, 0); - tcal.set(Calendar.HOUR_OF_DAY, 0); - tcal.set(Calendar.DAY_OF_MONTH, day); - tcal.set(Calendar.MONTH, mon - 1); - tcal.set(Calendar.YEAR, cl.get(Calendar.YEAR)); + LocalDateTimeLegacyWrapper tcal = new LocalDateTimeLegacyWrapper(LocalDateTime.now(timeZone)); + tcal.setSecond(0); + tcal.setMinute(0); + tcal.setHour(0); + tcal.setDayOfMonth(day); + tcal.setMonth(mon - 1); + tcal.setYear(cl.getYear()); - int ldom = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); - int dow = tcal.get(Calendar.DAY_OF_WEEK); + int ldom = getLastDayOfMonth(mon, cl.getYear()); + int dow = tcal.getDayOfWeek(); if (dow == Calendar.SATURDAY && day == 1) { day += 2; @@ -454,13 +464,12 @@ public long getNextValidTimeAfter(final long time) { day += 1; } - tcal.set(Calendar.SECOND, sec); - tcal.set(Calendar.MINUTE, min); - tcal.set(Calendar.HOUR_OF_DAY, hr); - tcal.set(Calendar.DAY_OF_MONTH, day); - tcal.set(Calendar.MONTH, mon - 1); - long nTime = tcal.getTimeInMillis(); - if (nTime < afterTime) { + tcal.setSecond(sec); + tcal.setMinute(min); + tcal.setHour(hr); + tcal.setDayOfMonth(day); + tcal.setMonth(mon - 1); + if (tcal.isAfter(afterTimeLdt)) { day = daysOfMonth.first(); mon++; } @@ -468,7 +477,7 @@ public long getNextValidTimeAfter(final long time) { t = day; day = st.first(); // make sure we don't over-run a short month, such as february - int lastDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + int lastDay = getLastDayOfMonth(mon, cl.getYear()); if (day > lastDay) { day = daysOfMonth.first(); mon++; @@ -479,11 +488,11 @@ public long getNextValidTimeAfter(final long time) { } if (day != t || mon != tmon) { - cl.set(Calendar.SECOND, 0); - cl.set(Calendar.MINUTE, 0); - cl.set(Calendar.HOUR_OF_DAY, 0); - cl.set(Calendar.DAY_OF_MONTH, day); - cl.set(Calendar.MONTH, mon - 1); + cl.setSecond(0); + cl.setMinute(0); + cl.setHour(0); + cl.setDayOfMonth(day); + cl.setMonth(mon - 1); // '- 1' because calendar is 0-based for this field, and we // are 1-based continue; @@ -493,7 +502,7 @@ public long getNextValidTimeAfter(final long time) { // the month? int dow = daysOfWeek.first(); // desired // d-o-w - int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int cDow = cl.getDayOfWeek(); // current d-o-w int daysToAdd = 0; if (cDow < dow) { daysToAdd = dow - cDow; @@ -502,15 +511,15 @@ public long getNextValidTimeAfter(final long time) { daysToAdd = dow + (7 - cDow); } - int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + int lDay = getLastDayOfMonth(mon, cl.getYear()); if (day + daysToAdd > lDay) { // did we already miss the // last one? - cl.set(Calendar.SECOND, 0); - cl.set(Calendar.MINUTE, 0); - cl.set(Calendar.HOUR_OF_DAY, 0); - cl.set(Calendar.DAY_OF_MONTH, 1); - cl.set(Calendar.MONTH, mon); + cl.setSecond(0); + cl.setMinute(0); + cl.setHour(0); + cl.setDayOfMonth(1); + cl.setMonth(mon); // no '- 1' here because we are promoting the month continue; } @@ -523,11 +532,11 @@ public long getNextValidTimeAfter(final long time) { day += daysToAdd; if (daysToAdd > 0) { - cl.set(Calendar.SECOND, 0); - cl.set(Calendar.MINUTE, 0); - cl.set(Calendar.HOUR_OF_DAY, 0); - cl.set(Calendar.DAY_OF_MONTH, day); - cl.set(Calendar.MONTH, mon - 1); + cl.setSecond(0); + cl.setMinute(0); + cl.setHour(0); + cl.setDayOfMonth(day); + cl.setMonth(mon - 1); // '- 1' here because we are not promoting the month continue; } @@ -536,7 +545,7 @@ public long getNextValidTimeAfter(final long time) { // are we looking for the Nth XXX day in the month? int dow = daysOfWeek.first(); // desired // d-o-w - int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int cDow = cl.getDayOfWeek(); // current d-o-w int daysToAdd = 0; if (cDow < dow) { daysToAdd = dow - cDow; @@ -557,25 +566,25 @@ public long getNextValidTimeAfter(final long time) { daysToAdd = (nthdayOfWeek - weekOfMonth) * 7; day += daysToAdd; - if (daysToAdd < 0 || day > getLastDayOfMonth(mon, cl.get(Calendar.YEAR))) { - cl.set(Calendar.SECOND, 0); - cl.set(Calendar.MINUTE, 0); - cl.set(Calendar.HOUR_OF_DAY, 0); - cl.set(Calendar.DAY_OF_MONTH, 1); - cl.set(Calendar.MONTH, mon); + if (daysToAdd < 0 || day > getLastDayOfMonth(mon, cl.getYear())) { + cl.setSecond(0); + cl.setMinute(0); + cl.setHour(0); + cl.setDayOfMonth(1); + cl.setMonth(mon); // no '- 1' here because we are promoting the month continue; } else if (daysToAdd > 0 || dayShifted) { - cl.set(Calendar.SECOND, 0); - cl.set(Calendar.MINUTE, 0); - cl.set(Calendar.HOUR_OF_DAY, 0); - cl.set(Calendar.DAY_OF_MONTH, day); - cl.set(Calendar.MONTH, mon - 1); + cl.setSecond(0); + cl.setMinute(0); + cl.setHour(0); + cl.setDayOfMonth(day); + cl.setMonth(mon - 1); // '- 1' here because we are NOT promoting the month continue; } } else { - int cDow = cl.get(Calendar.DAY_OF_WEEK); // current d-o-w + int cDow = cl.getDayOfWeek(); // current d-o-w int dow = daysOfWeek.first(); // desired // d-o-w st = daysOfWeek.tailSet(cDow); @@ -591,23 +600,23 @@ public long getNextValidTimeAfter(final long time) { daysToAdd = dow + (7 - cDow); } - int lDay = getLastDayOfMonth(mon, cl.get(Calendar.YEAR)); + int lDay = getLastDayOfMonth(mon, cl.getYear()); if (day + daysToAdd > lDay) { // will we pass the end of // the month? - cl.set(Calendar.SECOND, 0); - cl.set(Calendar.MINUTE, 0); - cl.set(Calendar.HOUR_OF_DAY, 0); - cl.set(Calendar.DAY_OF_MONTH, 1); - cl.set(Calendar.MONTH, mon); + cl.setSecond(0); + cl.setMinute(0); + cl.setHour(0); + cl.setDayOfMonth(1); + cl.setMonth(mon); // no '- 1' here because we are promoting the month continue; } else if (daysToAdd > 0) { // are we swithing days? - cl.set(Calendar.SECOND, 0); - cl.set(Calendar.MINUTE, 0); - cl.set(Calendar.HOUR_OF_DAY, 0); - cl.set(Calendar.DAY_OF_MONTH, day + daysToAdd); - cl.set(Calendar.MONTH, mon - 1); + cl.setSecond(0); + cl.setMinute(0); + cl.setHour(0); + cl.setDayOfMonth(day + daysToAdd); + cl.setMonth(mon - 1); // '- 1' because calendar is 0-based for this field, // and we are 1-based continue; @@ -618,12 +627,12 @@ public long getNextValidTimeAfter(final long time) { // throw new UnsupportedOperationException( // "Support for specifying both a day-of-week AND a day-of-month parameter is not implemented."); } - cl.set(Calendar.DAY_OF_MONTH, day); + cl.setDayOfMonth(day); - mon = cl.get(Calendar.MONTH) + 1; + mon = cl.getMonth() + 1; // '+ 1' because calendar is 0-based for this field, and we are // 1-based - int year = cl.get(Calendar.YEAR); + int year = cl.getYear(); t = -1; // test for expressions that never generate a valid fire date, @@ -643,21 +652,21 @@ public long getNextValidTimeAfter(final long time) { year++; } if (mon != t) { - cl.set(Calendar.SECOND, 0); - cl.set(Calendar.MINUTE, 0); - cl.set(Calendar.HOUR_OF_DAY, 0); - cl.set(Calendar.DAY_OF_MONTH, 1); - cl.set(Calendar.MONTH, mon - 1); + cl.setSecond(0); + cl.setMinute(0); + cl.setHour(0); + cl.setDayOfMonth(1); + cl.setMonth(mon - 1); // '- 1' because calendar is 0-based for this field, and we are // 1-based - cl.set(Calendar.YEAR, year); + cl.setYear(year); continue; } - cl.set(Calendar.MONTH, mon - 1); + cl.setMonth(mon - 1); // '- 1' because calendar is 0-based for this field, and we are // 1-based - year = cl.get(Calendar.YEAR); + year = cl.getYear(); t = -1; // get year................................................... @@ -671,22 +680,24 @@ public long getNextValidTimeAfter(final long time) { } if (year != t) { - cl.set(Calendar.SECOND, 0); - cl.set(Calendar.MINUTE, 0); - cl.set(Calendar.HOUR_OF_DAY, 0); - cl.set(Calendar.DAY_OF_MONTH, 1); - cl.set(Calendar.MONTH, 0); + cl.setSecond(0); + cl.setMinute(0); + cl.setHour(0); + cl.setDayOfMonth(1); + cl.setMonth(0); // '- 1' because calendar is 0-based for this field, and we are // 1-based - cl.set(Calendar.YEAR, year); + cl.setYear(year); continue; } - cl.set(Calendar.YEAR, year); + cl.setYear(year); gotOne = true; } // while( done == false ) - return cl.getTimeInMillis(); + LocalDateTime nextRuntime = cl.getLocalDateTime(); + + return nextRuntime.atZone(timeZone).toInstant().toEpochMilli(); } public String expression() { @@ -735,7 +746,7 @@ public String getExpressionSummary() { @Override public int hashCode() { - return Objects.hash(expression); + return Objects.hash(expression, timeZone); } @Override @@ -747,7 +758,7 @@ public boolean equals(Object obj) { return false; } final Cron other = (Cron) obj; - return Objects.equals(this.expression, other.expression); + return Objects.equals(this.expression, other.expression) && Objects.equals(this.timeZone, other.timeZone); } /** @@ -757,7 +768,7 @@ public boolean equals(Object obj) { */ @Override public String toString() { - return expression; + return "Cron{" + "timeZone=" + timeZone + ", expression='" + expression + '\'' + '}'; } /** @@ -1430,7 +1441,7 @@ private static int getLastDayOfMonth(int monthNum, int year) { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - return builder.value(toString()); + return builder.value(expression); } private static class ValueSet { diff --git a/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/scheduler/LocalDateTimeLegacyWrapper.java b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/scheduler/LocalDateTimeLegacyWrapper.java new file mode 100644 index 0000000000000..e540acc8042eb --- /dev/null +++ b/x-pack/plugin/core/src/main/java/org/elasticsearch/xpack/core/scheduler/LocalDateTimeLegacyWrapper.java @@ -0,0 +1,130 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.core.scheduler; + +import java.time.LocalDateTime; +import java.time.chrono.ChronoLocalDateTime; + +/** + * This class is designed to wrap the LocalDateTime class in order to make it behave, in terms of mutation, like a legacy Calendar class. + * This is to provide compatibility with the existing Cron next runtime calculation algorithm which relies on certain quirks of the Calendar + * such as days of the week being numbered starting on Sunday==1 and being able to set the current hour to 24 and have it roll over to + * midnight the next day. + */ +public class LocalDateTimeLegacyWrapper { + + private LocalDateTime ldt; + + public LocalDateTimeLegacyWrapper(LocalDateTime ldt) { + this.ldt = ldt; + } + + public int getYear() { + return ldt.getYear(); + } + + public int getDayOfMonth() { + return ldt.getDayOfMonth(); + } + + public int getHour() { + return ldt.getHour(); + } + + public int getMinute() { + return ldt.getMinute(); + } + + public int getSecond() { + return ldt.getSecond(); + } + + public int getDayOfWeek() { + return (ldt.getDayOfWeek().getValue() % 7) + 1; + } + + public int getMonth() { + return ldt.getMonthValue() - 1; + } + + public void setYear(int year) { + ldt = ldt.withYear(year); + } + + public void setDayOfMonth(int dayOfMonth) { + var lengthOfMonth = ldt.getMonth().length(ldt.toLocalDate().isLeapYear()); + if (dayOfMonth <= lengthOfMonth) { + ldt = ldt.withDayOfMonth(dayOfMonth); + } else { + var months = dayOfMonth / lengthOfMonth; + var day = dayOfMonth % lengthOfMonth; + ldt = ldt.plusMonths(months).withDayOfMonth(day); + } + } + + public void setMonth(int month) { + month++; // Months are 0-based in Calendar + if (month <= 12) { + ldt = ldt.withMonth(month); + } else { + var years = month / 12; + var monthOfYear = month % 12; + ldt = ldt.plusYears(years).withMonth(monthOfYear); + } + } + + public void setHour(int hour) { + if (hour < 24) { + ldt = ldt.withHour(hour); + } else { + var days = hour / 24; + var hourOfDay = hour % 24; + ldt = ldt.plusDays(days).withHour(hourOfDay); + } + } + + public void setMinute(int minute) { + if (minute < 60) { + ldt = ldt.withMinute(minute); + } else { + var hours = minute / 60; + var minuteOfHour = minute % 60; + ldt = ldt.plusHours(hours).withMinute(minuteOfHour); + } + } + + public void setSecond(int second) { + if (second < 60) { + ldt = ldt.withSecond(second); + } else { + var minutes = second / 60; + var secondOfMinute = second % 60; + ldt = ldt.plusMinutes(minutes).withSecond(secondOfMinute); + } + } + + public void plusYears(long years) { + ldt = ldt.plusYears(years); + } + + public void plusSeconds(long seconds) { + ldt = ldt.plusSeconds(seconds); + } + + public boolean isAfter(ChronoLocalDateTime other) { + return ldt.isAfter(other); + } + + public boolean isBefore(ChronoLocalDateTime other) { + return ldt.isBefore(other); + } + + public LocalDateTime getLocalDateTime() { + return ldt; + } +} diff --git a/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/scheduler/CronTimezoneTests.java b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/scheduler/CronTimezoneTests.java new file mode 100644 index 0000000000000..1e469002457d8 --- /dev/null +++ b/x-pack/plugin/core/src/test/java/org/elasticsearch/xpack/core/scheduler/CronTimezoneTests.java @@ -0,0 +1,231 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.core.scheduler; + +import org.elasticsearch.test.ESTestCase; +import org.hamcrest.Matchers; + +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZoneOffset; +import java.time.ZonedDateTime; +import java.time.temporal.ChronoUnit; +import java.time.zone.ZoneOffsetTransition; +import java.time.zone.ZoneRules; + +import static java.time.Instant.ofEpochMilli; +import static java.util.TimeZone.getTimeZone; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; + +public class CronTimezoneTests extends ESTestCase { + + public void testForFixedOffsetCorrectlyCalculateNextRuntime() { + Cron cron = new Cron("0 0 2 * * ?", ZoneOffset.of("+1")); + long midnightUTC = Instant.parse("2020-01-01T00:00:00Z").toEpochMilli(); + long nextValidTimeAfter = cron.getNextValidTimeAfter(midnightUTC); + assertThat(Instant.ofEpochMilli(nextValidTimeAfter), equalTo(Instant.parse("2020-01-01T01:00:00Z"))); + } + + public void testForLondonFixedDSTTransitionCheckCorrectSchedule() { + ZoneId londonZone = getTimeZone("Europe/London").toZoneId(); + + Cron cron = new Cron("0 0 2 * * ?", londonZone); + ZoneRules londonZoneRules = londonZone.getRules(); + Instant springMidnight = Instant.parse("2020-03-01T00:00:00Z"); + long timeBeforeDST = springMidnight.toEpochMilli(); + + assertThat(cron.getNextValidTimeAfter(timeBeforeDST), equalTo(Instant.parse("2020-03-01T02:00:00Z").toEpochMilli())); + + ZoneOffsetTransition zoneOffsetTransition = londonZoneRules.nextTransition(springMidnight); + + Instant timeAfterDST = zoneOffsetTransition.getDateTimeBefore() + .plusDays(1) + .atZone(ZoneOffset.UTC) + .withHour(0) + .withMinute(0) + .toInstant(); + + assertThat(cron.getNextValidTimeAfter(timeAfterDST.toEpochMilli()), equalTo(Instant.parse("2020-03-30T01:00:00Z").toEpochMilli())); + } + + public void testRandomDSTTransitionCalculateNextTimeCorrectlyRelativeToUTC() { + ZoneId timeZone = generateRandomDSTZone(); + + logger.info("Testing for timezone {}", timeZone); + + ZoneOffsetTransition zoneOffsetTransition = timeZone.getRules().nextTransition(Instant.now()); + + ZonedDateTime midnightBefore = zoneOffsetTransition.getDateTimeBefore().atZone(timeZone).minusDays(2).withHour(0).withMinute(0); + ZonedDateTime midnightAfter = zoneOffsetTransition.getDateTimeAfter().atZone(timeZone).plusDays(2).withHour(0).withMinute(0); + + long epochBefore = midnightBefore.toInstant().toEpochMilli(); + long epochAfter = midnightAfter.toInstant().toEpochMilli(); + + Cron cron = new Cron("0 0 2 * * ?", timeZone); + + long nextScheduleBefore = cron.getNextValidTimeAfter(epochBefore); + long nextScheduleAfter = cron.getNextValidTimeAfter(epochAfter); + + assertThat(nextScheduleBefore - epochBefore, equalTo(2 * 60 * 60 * 1000L)); // 2 hours + assertThat(nextScheduleAfter - epochAfter, equalTo(2 * 60 * 60 * 1000L)); // 2 hours + + ZonedDateTime utcMidnightBefore = zoneOffsetTransition.getDateTimeBefore() + .atZone(ZoneOffset.UTC) + .minusDays(2) + .withHour(0) + .withMinute(0); + + ZonedDateTime utcMidnightAfter = zoneOffsetTransition.getDateTimeAfter() + .atZone(ZoneOffset.UTC) + .plusDays(2) + .withHour(0) + .withMinute(0); + + long utcEpochBefore = utcMidnightBefore.toInstant().toEpochMilli(); + long utcEpochAfter = utcMidnightAfter.toInstant().toEpochMilli(); + + long nextUtcScheduleBefore = cron.getNextValidTimeAfter(utcEpochBefore); + long nextUtcScheduleAfter = cron.getNextValidTimeAfter(utcEpochAfter); + + assertThat(nextUtcScheduleBefore - utcEpochBefore, not(equalTo(nextUtcScheduleAfter - utcEpochAfter))); + + } + + private ZoneId generateRandomDSTZone() { + ZoneId timeZone; + int i = 0; + boolean found; + do { + timeZone = randomZone(); + found = getTimeZone(timeZone).useDaylightTime(); + i++; + } while (found == false && i <= 500); // Infinite loop prevention + + if (found == false) { + fail("Could not find a timezone with DST"); + } + + logger.debug("Testing for timezone {} after {} iterations", timeZone, i); + return timeZone; + } + + public void testForGMTGapTransitionTriggerTimeIsAsIfTransitionHasntHappenedYet() { + ZoneId london = ZoneId.of("Europe/London"); + Cron cron = new Cron("0 30 1 * * ?", london); // Every day at 1:30 + + Instant beforeTransition = Instant.parse("2025-03-30T00:00:00Z"); + long beforeTransitionEpoch = beforeTransition.toEpochMilli(); + + long nextValidTimeAfter = cron.getNextValidTimeAfter(beforeTransitionEpoch); + assertThat(ofEpochMilli(nextValidTimeAfter), equalTo(Instant.parse("2025-03-30T01:30:00Z"))); + } + + public void testForGMTOverlapTransitionTriggerSkipSecondExecution() { + ZoneId london = ZoneId.of("Europe/London"); + Cron cron = new Cron("0 30 1 * * ?", london); // Every day at 01:30 + + Instant beforeTransition = Instant.parse("2024-10-27T00:00:00Z"); + long beforeTransitionEpoch = beforeTransition.toEpochMilli(); + + long firstValidTimeAfter = cron.getNextValidTimeAfter(beforeTransitionEpoch); + assertThat(ofEpochMilli(firstValidTimeAfter), equalTo(Instant.parse("2024-10-27T00:30:00Z"))); + + long nextValidTimeAfter = cron.getNextValidTimeAfter(firstValidTimeAfter); + assertThat(ofEpochMilli(nextValidTimeAfter), equalTo(Instant.parse("2024-10-28T01:30:00Z"))); + } + + // This test checks that once per minute crons will be unaffected by a DST transition + public void testDiscontinuityResolutionForNonHourCronInRandomTimezone() { + var timezone = generateRandomDSTZone(); + + var cron = new Cron("0 * * * * ?", timezone); // Once per minute + + Instant referenceTime = randomInstantBetween(Instant.now(), Instant.now().plus(1826, ChronoUnit.DAYS)); // ~5 years + ZoneOffsetTransition transition1 = timezone.getRules().nextTransition(referenceTime); + + // Currently there are no known timezones with DST transitions shorter than 10 minutes but this guards against future changes + if (Math.abs(transition1.getOffsetBefore().getTotalSeconds() - transition1.getOffsetAfter().getTotalSeconds()) < 600) { + fail("Transition is not long enough to test"); + } + + testNonHourCronTransition(transition1, cron); + + var transition2 = timezone.getRules().nextTransition(transition1.getInstant().plus(1, ChronoUnit.DAYS)); + + testNonHourCronTransition(transition2, cron); + + } + + private static void testNonHourCronTransition(ZoneOffsetTransition transition, Cron cron) { + Instant insideTransition; + if (transition.isGap()) { + insideTransition = transition.getInstant().plus(10, ChronoUnit.MINUTES); + Instant nextTrigger = ofEpochMilli(cron.getNextValidTimeAfter(insideTransition.toEpochMilli())); + assertThat(nextTrigger, equalTo(insideTransition.plus(1, ChronoUnit.MINUTES))); + } else { + insideTransition = transition.getInstant().minus(10, ChronoUnit.MINUTES); + Instant nextTrigger = ofEpochMilli(cron.getNextValidTimeAfter(insideTransition.toEpochMilli())); + assertThat(nextTrigger, equalTo(insideTransition.plus(1, ChronoUnit.MINUTES))); + + insideTransition = insideTransition.plus(transition.getDuration()); + nextTrigger = ofEpochMilli(cron.getNextValidTimeAfter(insideTransition.toEpochMilli())); + assertThat(nextTrigger, equalTo(insideTransition.plus(1, ChronoUnit.MINUTES))); + } + } + + // This test checks that once per day crons will behave correctly during a DST transition + public void testDiscontinuityResolutionForCronInRandomTimezone() { + var timezone = generateRandomDSTZone(); + + Instant referenceTime = randomInstantBetween(Instant.now(), Instant.now().plus(1826, ChronoUnit.DAYS)); // ~5 years + ZoneOffsetTransition transition1 = timezone.getRules().nextTransition(referenceTime); + + // Currently there are no known timezones with DST transitions shorter than 10 minutes but this guards against future changes + if (Math.abs(transition1.getOffsetBefore().getTotalSeconds() - transition1.getOffsetAfter().getTotalSeconds()) < 600) { + fail("Transition is not long enough to test"); + } + + testHourCronTransition(transition1, timezone); + + var transition2 = timezone.getRules().nextTransition(transition1.getInstant().plus(1, ChronoUnit.DAYS)); + + testHourCronTransition(transition2, timezone); + } + + private static void testHourCronTransition(ZoneOffsetTransition transition, ZoneId timezone) { + if (transition.isGap()) { + LocalDateTime targetTime = transition.getDateTimeBefore().plusMinutes(10); + + var cron = new Cron("0 " + targetTime.getMinute() + " " + targetTime.getHour() + " * * ?", timezone); + + long nextTrigger = cron.getNextValidTimeAfter(transition.getInstant().minus(10, ChronoUnit.MINUTES).toEpochMilli()); + + assertThat(ofEpochMilli(nextTrigger), equalTo(transition.getInstant().plus(10, ChronoUnit.MINUTES))); + } else { + LocalDateTime targetTime = transition.getDateTimeAfter().plusMinutes(10); + var cron = new Cron("0 " + targetTime.getMinute() + " " + targetTime.getHour() + " * * ?", timezone); + + long transitionLength = Math.abs(transition.getDuration().toSeconds()); + long firstTrigger = cron.getNextValidTimeAfter( + transition.getInstant().minusSeconds(transitionLength).minus(10, ChronoUnit.MINUTES).toEpochMilli() + ); + + assertThat( + ofEpochMilli(firstTrigger), + equalTo(transition.getInstant().minusSeconds(transitionLength).plus(10, ChronoUnit.MINUTES)) + ); + + var repeatTrigger = cron.getNextValidTimeAfter(firstTrigger + (1000 * 60L)); // 1 minute + + assertThat(repeatTrigger - firstTrigger, Matchers.greaterThan(24 * 60 * 60 * 1000L)); // 24 hours + } + } + +} diff --git a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorCustomSchedule.java b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorCustomSchedule.java index 7badf6926c574..387224408a14b 100644 --- a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorCustomSchedule.java +++ b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorCustomSchedule.java @@ -140,7 +140,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws public void writeTo(StreamOutput out) throws IOException { out.writeWriteable(configurationOverrides); out.writeBoolean(enabled); - out.writeString(interval.toString()); + out.writeString(interval.expression()); out.writeOptionalInstant(lastSynced); out.writeString(name); } diff --git a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorScheduling.java b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorScheduling.java index 3c08a5ac1e218..008cbca0cd5ea 100644 --- a/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorScheduling.java +++ b/x-pack/plugin/ent-search/src/main/java/org/elasticsearch/xpack/application/connector/ConnectorScheduling.java @@ -222,7 +222,7 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws @Override public void writeTo(StreamOutput out) throws IOException { out.writeBoolean(enabled); - out.writeString(interval.toString()); + out.writeString(interval.expression()); } @Override diff --git a/x-pack/plugin/slm/src/test/java/org/elasticsearch/xpack/slm/SnapshotLifecyclePolicyTests.java b/x-pack/plugin/slm/src/test/java/org/elasticsearch/xpack/slm/SnapshotLifecyclePolicyTests.java index b7674a2d60bff..0ab3e99e1efc9 100644 --- a/x-pack/plugin/slm/src/test/java/org/elasticsearch/xpack/slm/SnapshotLifecyclePolicyTests.java +++ b/x-pack/plugin/slm/src/test/java/org/elasticsearch/xpack/slm/SnapshotLifecyclePolicyTests.java @@ -64,12 +64,12 @@ public void testNextExecutionTimeSchedule() { SnapshotLifecyclePolicy p = new SnapshotLifecyclePolicy( "id", "name", - "0 1 2 3 4 ? 2099", + "0 1 2 3 4 ? 2049", "repo", Collections.emptyMap(), SnapshotRetentionConfiguration.EMPTY ); - assertThat(p.calculateNextExecution(-1, Clock.systemUTC()), equalTo(4078864860000L)); + assertThat(p.calculateNextExecution(-1, Clock.systemUTC()), equalTo(2501028060000L)); } public void testNextExecutionTimeInterval() { diff --git a/x-pack/plugin/watcher/qa/rest/src/yamlRestTest/resources/rest-api-spec/test/watcher/put_watch/11_timezoned_schedules.yml b/x-pack/plugin/watcher/qa/rest/src/yamlRestTest/resources/rest-api-spec/test/watcher/put_watch/11_timezoned_schedules.yml new file mode 100644 index 0000000000000..0371443367603 --- /dev/null +++ b/x-pack/plugin/watcher/qa/rest/src/yamlRestTest/resources/rest-api-spec/test/watcher/put_watch/11_timezoned_schedules.yml @@ -0,0 +1,121 @@ +--- +setup: + - do: + cluster.health: + wait_for_status: yellow + +--- +"Test put watch api with timezone": + - do: + watcher.put_watch: + id: "my_watch" + body: > + { + "trigger": { + "schedule": { + "timezone": "America/Los_Angeles", + "hourly": { + "minute": [ 0, 5 ] + } + } + }, + "input": { + "simple": { + "payload": { + "send": "yes" + } + } + }, + "condition": { + "always": {} + }, + "actions": { + "test_index": { + "index": { + "index": "test" + } + } + } + } + - match: { _id: "my_watch" } + - do: + watcher.get_watch: + id: "my_watch" + - match: { watch.trigger.schedule.timezone: "America/Los_Angeles" } + +--- +"Test put watch api without timezone": + - do: + watcher.put_watch: + id: "my_watch" + body: > + { + "trigger": { + "schedule": { + "hourly": { + "minute": [ 0, 5 ] + } + } + }, + "input": { + "simple": { + "payload": { + "send": "yes" + } + } + }, + "condition": { + "always": {} + }, + "actions": { + "test_index": { + "index": { + "index": "test" + } + } + } + } + - match: { _id: "my_watch" } + - do: + watcher.get_watch: + id: "my_watch" + - is_false: watch.trigger.schedule.timezone + +--- +"Reject put watch with invalid timezone": + - do: + watcher.put_watch: + id: "my_watch" + body: > + { + "trigger": { + "schedule": { + "timezone": "Pangea/Tethys", + "hourly": { + "minute": [ 0, 5 ] + } + } + }, + "input": { + "simple": { + "payload": { + "send": "yes" + } + } + }, + "condition": { + "always": {} + }, + "actions": { + "test_index": { + "index": { + "index": "test" + } + } + } + } + catch: bad_request + - match: { error.type: "parse_exception" } + - match: { error.reason: "could not parse schedule. invalid timezone [Pangea/Tethys]" } + - match: { error.caused_by.type: "zone_rules_exception" } + - match: { error.caused_by.reason: "Unknown time-zone ID: Pangea/Tethys" } diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/CronnableSchedule.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/CronnableSchedule.java index 63e9dae88de41..0db99af9b3fc2 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/CronnableSchedule.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/CronnableSchedule.java @@ -8,6 +8,7 @@ import org.elasticsearch.xpack.core.scheduler.Cron; +import java.time.ZoneId; import java.util.Arrays; import java.util.Comparator; import java.util.Objects; @@ -17,6 +18,7 @@ public abstract class CronnableSchedule implements Schedule { private static final Comparator CRON_COMPARATOR = Comparator.comparing(Cron::expression); protected final Cron[] crons; + private ZoneId timeZone; CronnableSchedule(String... expressions) { this(crons(expressions)); @@ -28,6 +30,17 @@ private CronnableSchedule(Cron... crons) { Arrays.sort(crons, CRON_COMPARATOR); } + protected void setTimeZone(ZoneId timeZone) { + this.timeZone = timeZone; + for (Cron cron : crons) { + cron.setTimeZone(timeZone); + } + } + + public ZoneId getTimeZone() { + return timeZone; + } + @Override public long nextScheduledTimeAfter(long startTime, long time) { assert time >= startTime; @@ -45,21 +58,22 @@ public Cron[] crons() { return crons; } + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CronnableSchedule that = (CronnableSchedule) o; + return Objects.deepEquals(crons, that.crons) && Objects.equals(timeZone, that.timeZone); + } + @Override public int hashCode() { - return Objects.hash((Object[]) crons); + return Objects.hash(Arrays.hashCode(crons), timeZone); } @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null || getClass() != obj.getClass()) { - return false; - } - final CronnableSchedule other = (CronnableSchedule) obj; - return Objects.deepEquals(this.crons, other.crons); + public String toString() { + return "CronnableSchedule{" + "crons=" + Arrays.toString(crons) + ", timeZone=" + timeZone + '}'; } static Cron[] crons(String... expressions) { diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/ScheduleRegistry.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/ScheduleRegistry.java index 31cf46f8abaac..5d2259db71f77 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/ScheduleRegistry.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/ScheduleRegistry.java @@ -8,8 +8,11 @@ import org.elasticsearch.ElasticsearchParseException; import org.elasticsearch.xcontent.XContentParser; +import org.elasticsearch.xpack.watcher.trigger.schedule.support.TimezoneUtils; import java.io.IOException; +import java.time.DateTimeException; +import java.time.ZoneId; import java.util.HashMap; import java.util.Map; import java.util.Set; @@ -29,9 +32,15 @@ public Schedule parse(String context, XContentParser parser) throws IOException String type = null; XContentParser.Token token; Schedule schedule = null; + ZoneId timeZone = null; // Default to UTC while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) { if (token == XContentParser.Token.FIELD_NAME) { - type = parser.currentName(); + var fieldName = parser.currentName(); + if (fieldName.equals(ScheduleTrigger.TIMEZONE_FIELD)) { + timeZone = parseTimezone(parser); + } else { + type = parser.currentName(); + } } else if (type != null) { schedule = parse(context, type, parser); } else { @@ -44,9 +53,38 @@ public Schedule parse(String context, XContentParser parser) throws IOException if (schedule == null) { throw new ElasticsearchParseException("could not parse schedule. expected a schedule type field, but no fields were found"); } + + if (timeZone != null && schedule instanceof CronnableSchedule cronnableSchedule) { + cronnableSchedule.setTimeZone(timeZone); + } else if (timeZone != null) { + throw new ElasticsearchParseException( + "could not parse schedule. Timezone is not supported for schedule type [{}]", + schedule.type() + ); + } + return schedule; } + private static ZoneId parseTimezone(XContentParser parser) throws IOException { + ZoneId timeZone; + XContentParser.Token token = parser.nextToken(); + if (token == XContentParser.Token.VALUE_STRING) { + String text = parser.text(); + try { + timeZone = TimezoneUtils.parse(text); + } catch (DateTimeException e) { + throw new ElasticsearchParseException("could not parse schedule. invalid timezone [{}]", e, text); + } + } else { + throw new ElasticsearchParseException( + "could not parse schedule. expected a string value for timezone, but found [{}] instead", + token + ); + } + return timeZone; + } + public Schedule parse(String context, String type, XContentParser parser) throws IOException { Schedule.Parser scheduleParser = parsers.get(type); if (scheduleParser == null) { diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/ScheduleTrigger.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/ScheduleTrigger.java index 4a67841e6c88e..cc6ec8f5aaa57 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/ScheduleTrigger.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/ScheduleTrigger.java @@ -14,6 +14,7 @@ public class ScheduleTrigger implements Trigger { public static final String TYPE = "schedule"; + public static final String TIMEZONE_FIELD = "timezone"; private final Schedule schedule; @@ -49,7 +50,13 @@ public int hashCode() { @Override public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { - return builder.startObject().field(schedule.type(), schedule, params).endObject(); + builder.startObject(); + if (schedule instanceof CronnableSchedule cronnableSchedule && cronnableSchedule.getTimeZone() != null) { + builder.field(TIMEZONE_FIELD, cronnableSchedule.getTimeZone().getId()); + } + + builder.field(schedule.type(), schedule, params); + return builder.endObject(); } public static Builder builder(Schedule schedule) { diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/support/TimezoneUtils.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/support/TimezoneUtils.java new file mode 100644 index 0000000000000..c77fdda803bec --- /dev/null +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/support/TimezoneUtils.java @@ -0,0 +1,55 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.watcher.trigger.schedule.support; + +import java.time.DateTimeException; +import java.time.ZoneId; +import java.util.Locale; +import java.util.Map; + +import static java.util.stream.Collectors.toMap; + +/** + * Utility class for dealing with Timezone related operations. + */ +public class TimezoneUtils { + + private static final Map caseInsensitiveTZLookup; + + static { + caseInsensitiveTZLookup = ZoneId.getAvailableZoneIds() + .stream() + .collect(toMap(zoneId -> zoneId.toLowerCase(Locale.ROOT), ZoneId::of)); + } + + /** + * Parses a timezone string into a {@link ZoneId} object. The timezone string can be a valid timezone ID, or a + * timezone offset string and is case-insensitive. + * + * @param timezoneString The timezone string to parse + * @return The parsed {@link ZoneId} object + * @throws DateTimeException If the timezone string is not a valid timezone ID or offset + */ + public static ZoneId parse(String timezoneString) throws DateTimeException { + try { + return ZoneId.of(timezoneString); + } catch (DateTimeException e) { + ZoneId timeZone = caseInsensitiveTZLookup.get(timezoneString.toLowerCase(Locale.ROOT)); + if (timeZone != null) { + return timeZone; + } + try { + return ZoneId.of(timezoneString.toUpperCase(Locale.ROOT)); + } catch (DateTimeException ignored) { + // ignore + } + throw e; + } + } + +} diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/trigger/schedule/ScheduleRegistryTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/trigger/schedule/ScheduleRegistryTests.java index 7fc4739c342f1..aa39701d207c3 100644 --- a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/trigger/schedule/ScheduleRegistryTests.java +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/trigger/schedule/ScheduleRegistryTests.java @@ -12,6 +12,7 @@ import org.elasticsearch.xcontent.json.JsonXContent; import org.junit.Before; +import java.time.ZoneId; import java.util.HashSet; import java.util.Set; @@ -49,15 +50,23 @@ public void testParserInterval() throws Exception { } public void testParseCron() throws Exception { - Object cron = randomBoolean() ? Schedules.cron("* 0/5 * * * ?") : Schedules.cron("* 0/2 * * * ?", "* 0/3 * * * ?", "* 0/5 * * * ?"); - XContentBuilder builder = jsonBuilder().startObject().field(CronSchedule.TYPE, cron).endObject(); + var cron = randomBoolean() ? Schedules.cron("* 0/5 * * * ?") : Schedules.cron("* 0/2 * * * ?", "* 0/3 * * * ?", "* 0/5 * * * ?"); + ZoneId timeZone = null; + XContentBuilder builder = jsonBuilder().startObject().field(CronSchedule.TYPE, cron); + if (randomBoolean()) { + timeZone = randomTimeZone().toZoneId(); + cron.setTimeZone(timeZone); + builder.field(ScheduleTrigger.TIMEZONE_FIELD, timeZone.getId()); + } + builder.endObject(); BytesReference bytes = BytesReference.bytes(builder); XContentParser parser = createParser(JsonXContent.jsonXContent, bytes); parser.nextToken(); - Schedule schedule = registry.parse("ctx", parser); + CronnableSchedule schedule = (CronnableSchedule) registry.parse("ctx", parser); assertThat(schedule, notNullValue()); assertThat(schedule, instanceOf(CronSchedule.class)); assertThat(schedule, is(cron)); + assertThat(schedule.getTimeZone(), equalTo(timeZone)); } public void testParseHourly() throws Exception { diff --git a/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/trigger/schedule/support/TimezoneUtilsTests.java b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/trigger/schedule/support/TimezoneUtilsTests.java new file mode 100644 index 0000000000000..aa797ec610eca --- /dev/null +++ b/x-pack/plugin/watcher/src/test/java/org/elasticsearch/xpack/watcher/trigger/schedule/support/TimezoneUtilsTests.java @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.watcher.trigger.schedule.support; + +import org.elasticsearch.test.ESTestCase; + +import java.time.ZoneId; +import java.util.Locale; + +import static org.hamcrest.Matchers.equalTo; + +public class TimezoneUtilsTests extends ESTestCase { + + public void testExpectedFormatParsing() { + assertThat(TimezoneUtils.parse("Europe/London").getId(), equalTo("Europe/London")); + assertThat(TimezoneUtils.parse("+1").getId(), equalTo("+01:00")); + assertThat(TimezoneUtils.parse("GMT+01:00").getId(), equalTo("GMT+01:00")); + } + + public void testParsingIsCaseInsensitive() { + ZoneId timeZone = randomTimeZone().toZoneId(); + assertThat(TimezoneUtils.parse(timeZone.getId()), equalTo(timeZone)); + assertThat(TimezoneUtils.parse(timeZone.getId().toLowerCase(Locale.ROOT)), equalTo(timeZone)); + assertThat(TimezoneUtils.parse(timeZone.getId().toUpperCase(Locale.ROOT)), equalTo(timeZone)); + } + + public void testParsingOffsets() { + ZoneId timeZone = ZoneId.of("GMT+01:00"); + assertThat(TimezoneUtils.parse("GMT+01:00"), equalTo(timeZone)); + assertThat(TimezoneUtils.parse("gmt+01:00"), equalTo(timeZone)); + assertThat(TimezoneUtils.parse("GMT+1"), equalTo(timeZone)); + + assertThat(TimezoneUtils.parse("+1"), equalTo(ZoneId.of("+01:00"))); + } +} From 97296598c3e8df2af53c2d49d8de97d16ef1dc56 Mon Sep 17 00:00:00 2001 From: Rene Groeschke Date: Mon, 25 Nov 2024 11:28:15 +0100 Subject: [PATCH 07/34] [Build] Tweak BWC tasks caching (#117423) * do not track certain env vars for LoggedExec * Fix some more tasks on build cacheability * Some more cleanup on task inputs * Mark more tasks as cacheable --- .../conventions/precommit/PomValidationTask.java | 3 +++ .../gradle/internal/BwcSetupExtension.java | 6 +++--- .../InternalDistributionBwcSetupPlugin.java | 3 ++- .../precommit/CheckstylePrecommitPlugin.java | 12 +++++++++--- .../internal/precommit/FilePermissionsTask.java | 3 +++ .../internal/test/rest/CopyRestTestsTask.java | 3 +++ .../java/org/elasticsearch/gradle/LoggedExec.java | 15 +++++++++++++-- .../plugin/GeneratePluginPropertiesTask.java | 5 +++++ 8 files changed, 41 insertions(+), 9 deletions(-) diff --git a/build-conventions/src/main/java/org/elasticsearch/gradle/internal/conventions/precommit/PomValidationTask.java b/build-conventions/src/main/java/org/elasticsearch/gradle/internal/conventions/precommit/PomValidationTask.java index 9d06e632ec928..89bab313a0069 100644 --- a/build-conventions/src/main/java/org/elasticsearch/gradle/internal/conventions/precommit/PomValidationTask.java +++ b/build-conventions/src/main/java/org/elasticsearch/gradle/internal/conventions/precommit/PomValidationTask.java @@ -16,6 +16,8 @@ import org.gradle.api.file.RegularFileProperty; import org.gradle.api.model.ObjectFactory; import org.gradle.api.tasks.InputFile; +import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.TaskAction; import java.io.FileReader; @@ -37,6 +39,7 @@ public PomValidationTask(ObjectFactory objects) { } @InputFile + @PathSensitive(PathSensitivity.RELATIVE) public RegularFileProperty getPomFile() { return pomFile; } diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/BwcSetupExtension.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/BwcSetupExtension.java index d7bf839817e12..5992a40275b46 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/BwcSetupExtension.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/BwcSetupExtension.java @@ -115,9 +115,9 @@ private static TaskProvider createRunBwcGradleTask( if (OS.current() == OS.WINDOWS) { loggedExec.getExecutable().set("cmd"); - loggedExec.args("/C", "call", new File(checkoutDir.get(), "gradlew").toString()); + loggedExec.args("/C", "call", "gradlew"); } else { - loggedExec.getExecutable().set(new File(checkoutDir.get(), "gradlew").toString()); + loggedExec.getExecutable().set("./gradlew"); } if (useUniqueUserHome) { @@ -177,7 +177,7 @@ private static String readFromFile(File file) { } } - public static abstract class JavaHomeValueSource implements ValueSource { + public abstract static class JavaHomeValueSource implements ValueSource { private String minimumCompilerVersionPath(Version bwcVersion) { return (bwcVersion.onOrAfter(BUILD_TOOL_MINIMUM_VERSION)) diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionBwcSetupPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionBwcSetupPlugin.java index 80fd6db59cf9f..c17127f9bbfcf 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionBwcSetupPlugin.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/InternalDistributionBwcSetupPlugin.java @@ -23,6 +23,7 @@ import org.gradle.api.provider.Provider; import org.gradle.api.provider.ProviderFactory; import org.gradle.api.tasks.Copy; +import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.TaskProvider; import org.gradle.jvm.toolchain.JavaToolchainService; import org.gradle.language.base.plugins.LifecycleBasePlugin; @@ -322,7 +323,7 @@ static void createBuildBwcTask( File expectedOutputFile = useNativeExpanded ? new File(projectArtifact.expandedDistDir, "elasticsearch-" + bwcVersion.get() + "-SNAPSHOT") : projectArtifact.distFile; - c.getInputs().file(new File(project.getBuildDir(), "refspec")); + c.getInputs().file(new File(project.getBuildDir(), "refspec")).withPathSensitivity(PathSensitivity.RELATIVE); if (useNativeExpanded) { c.getOutputs().dir(expectedOutputFile); } else { diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/CheckstylePrecommitPlugin.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/CheckstylePrecommitPlugin.java index 81ff081ffa82b..dbbe35905d208 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/CheckstylePrecommitPlugin.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/CheckstylePrecommitPlugin.java @@ -19,6 +19,7 @@ import org.gradle.api.plugins.quality.Checkstyle; import org.gradle.api.plugins.quality.CheckstyleExtension; import org.gradle.api.provider.Provider; +import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.SourceSetContainer; import org.gradle.api.tasks.TaskProvider; @@ -42,18 +43,23 @@ public TaskProvider createTask(Project project) { File checkstyleSuppressions = new File(checkstyleDir, "checkstyle_suppressions.xml"); File checkstyleConf = new File(checkstyleDir, "checkstyle.xml"); TaskProvider copyCheckstyleConf = project.getTasks().register("copyCheckstyleConf"); - // configure inputs and outputs so up to date works properly copyCheckstyleConf.configure(t -> t.getOutputs().files(checkstyleSuppressions, checkstyleConf)); if ("jar".equals(checkstyleConfUrl.getProtocol())) { try { JarURLConnection jarURLConnection = (JarURLConnection) checkstyleConfUrl.openConnection(); - copyCheckstyleConf.configure(t -> t.getInputs().file(jarURLConnection.getJarFileURL())); + copyCheckstyleConf.configure( + t -> t.getInputs().file(jarURLConnection.getJarFileURL()).withPathSensitivity(PathSensitivity.RELATIVE) + ); } catch (IOException e) { throw new UncheckedIOException(e); } } else if ("file".equals(checkstyleConfUrl.getProtocol())) { - copyCheckstyleConf.configure(t -> t.getInputs().files(checkstyleConfUrl.getFile(), checkstyleSuppressionsUrl.getFile())); + copyCheckstyleConf.configure( + t -> t.getInputs() + .files(checkstyleConfUrl.getFile(), checkstyleSuppressionsUrl.getFile()) + .withPathSensitivity(PathSensitivity.RELATIVE) + ); } // Explicitly using an Action interface as java lambdas diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/FilePermissionsTask.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/FilePermissionsTask.java index a198034c3c09b..479b6f431b867 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/FilePermissionsTask.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/precommit/FilePermissionsTask.java @@ -19,6 +19,8 @@ import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.api.tasks.StopExecutionException; import org.gradle.api.tasks.TaskAction; @@ -79,6 +81,7 @@ private static boolean isExecutableFile(File file) { @InputFiles @IgnoreEmptyDirectories @SkipWhenEmpty + @PathSensitive(PathSensitivity.RELATIVE) public FileCollection getFiles() { return getSources().get() .stream() diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/CopyRestTestsTask.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/CopyRestTestsTask.java index 02309bb9c1811..6890cfb652952 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/CopyRestTestsTask.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/test/rest/CopyRestTestsTask.java @@ -24,6 +24,8 @@ import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.OutputDirectory; +import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.SkipWhenEmpty; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.util.PatternFilterable; @@ -106,6 +108,7 @@ public Map getSubstitutions() { @SkipWhenEmpty @IgnoreEmptyDirectories @InputFiles + @PathSensitive(PathSensitivity.RELATIVE) public FileTree getInputDir() { FileTree coreFileTree = null; FileTree xpackFileTree = null; diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/LoggedExec.java b/build-tools/src/main/java/org/elasticsearch/gradle/LoggedExec.java index 505e9a5b114d1..28018b4c50abe 100644 --- a/build-tools/src/main/java/org/elasticsearch/gradle/LoggedExec.java +++ b/build-tools/src/main/java/org/elasticsearch/gradle/LoggedExec.java @@ -20,6 +20,7 @@ import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; import org.gradle.api.provider.ProviderFactory; +import org.gradle.api.tasks.CacheableTask; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Optional; @@ -53,6 +54,7 @@ * Exec task implementation. */ @SuppressWarnings("unchecked") +@CacheableTask public abstract class LoggedExec extends DefaultTask implements FileSystemOperationsAware { private static final Logger LOGGER = Logging.getLogger(LoggedExec.class); @@ -87,6 +89,14 @@ public abstract class LoggedExec extends DefaultTask implements FileSystemOperat abstract public Property getCaptureOutput(); @Input + public Provider getWorkingDirPath() { + return getWorkingDir().map(file -> { + String relativeWorkingDir = projectLayout.getProjectDirectory().getAsFile().toPath().relativize(file.toPath()).toString(); + return relativeWorkingDir; + }); + } + + @Internal abstract public Property getWorkingDir(); @Internal @@ -117,9 +127,10 @@ public LoggedExec( * can be reused across different build invocations. * */ private void setupDefaultEnvironment(ProviderFactory providerFactory) { - getEnvironment().putAll(providerFactory.environmentVariablesPrefixedBy("BUILDKITE")); getEnvironment().putAll(providerFactory.environmentVariablesPrefixedBy("GRADLE_BUILD_CACHE")); - getEnvironment().putAll(providerFactory.environmentVariablesPrefixedBy("VAULT")); + + getNonTrackedEnvironment().putAll(providerFactory.environmentVariablesPrefixedBy("BUILDKITE")); + getNonTrackedEnvironment().putAll(providerFactory.environmentVariablesPrefixedBy("VAULT")); Provider javaToolchainHome = providerFactory.environmentVariable("JAVA_TOOLCHAIN_HOME"); if (javaToolchainHome.isPresent()) { getEnvironment().put("JAVA_TOOLCHAIN_HOME", javaToolchainHome); diff --git a/build-tools/src/main/java/org/elasticsearch/gradle/plugin/GeneratePluginPropertiesTask.java b/build-tools/src/main/java/org/elasticsearch/gradle/plugin/GeneratePluginPropertiesTask.java index e144122f97770..6cf01814a45ef 100644 --- a/build-tools/src/main/java/org/elasticsearch/gradle/plugin/GeneratePluginPropertiesTask.java +++ b/build-tools/src/main/java/org/elasticsearch/gradle/plugin/GeneratePluginPropertiesTask.java @@ -19,10 +19,13 @@ import org.gradle.api.file.RegularFileProperty; import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Property; +import org.gradle.api.tasks.CacheableTask; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputFiles; import org.gradle.api.tasks.Optional; import org.gradle.api.tasks.OutputFile; +import org.gradle.api.tasks.PathSensitive; +import org.gradle.api.tasks.PathSensitivity; import org.gradle.api.tasks.TaskAction; import org.objectweb.asm.ClassReader; import org.objectweb.asm.tree.ClassNode; @@ -39,6 +42,7 @@ import javax.inject.Inject; +@CacheableTask public abstract class GeneratePluginPropertiesTask extends DefaultTask { public static final String PROPERTIES_FILENAME = "plugin-descriptor.properties"; @@ -82,6 +86,7 @@ public GeneratePluginPropertiesTask(ProjectLayout projectLayout) { public abstract Property getIsLicensed(); @InputFiles + @PathSensitive(PathSensitivity.RELATIVE) public abstract ConfigurableFileCollection getModuleInfoFile(); @OutputFile From 32aaacbd7b383188f2b5eb64fce69a09d11bfc94 Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Mon, 25 Nov 2024 12:09:30 +0100 Subject: [PATCH 08/34] LOOKUP JOIN using field-caps for field mapping (#117246) * LOOKUP JOIN using field-caps for field mapping Removes the hard-coded hack for languages_lookup, and instead does a field-caps check for the real join index. * Update docs/changelog/117246.yaml * Some code review comments --- docs/changelog/117246.yaml | 5 + .../xpack/esql/CsvTestsDataLoader.java | 9 +- .../resources/languages_lookup-settings.json | 5 + .../xpack/esql/analysis/Analyzer.java | 37 ++--- .../xpack/esql/analysis/AnalyzerContext.java | 14 +- .../xpack/esql/session/EsqlSession.java | 144 ++++++++++++------ 6 files changed, 135 insertions(+), 79 deletions(-) create mode 100644 docs/changelog/117246.yaml create mode 100644 x-pack/plugin/esql/qa/testFixtures/src/main/resources/languages_lookup-settings.json diff --git a/docs/changelog/117246.yaml b/docs/changelog/117246.yaml new file mode 100644 index 0000000000000..29c4464855967 --- /dev/null +++ b/docs/changelog/117246.yaml @@ -0,0 +1,5 @@ +pr: 117246 +summary: LOOKUP JOIN using field-caps for field mapping +area: ES|QL +type: enhancement +issues: [] diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java index 0d6659ad37a27..ffbac2829ea4a 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/java/org/elasticsearch/xpack/esql/CsvTestsDataLoader.java @@ -56,6 +56,8 @@ public class CsvTestsDataLoader { private static final TestsDataset APPS = new TestsDataset("apps"); private static final TestsDataset APPS_SHORT = APPS.withIndex("apps_short").withTypeMapping(Map.of("id", "short")); private static final TestsDataset LANGUAGES = new TestsDataset("languages"); + private static final TestsDataset LANGUAGES_LOOKUP = LANGUAGES.withIndex("languages_lookup") + .withSetting("languages_lookup-settings.json"); private static final TestsDataset ALERTS = new TestsDataset("alerts"); private static final TestsDataset UL_LOGS = new TestsDataset("ul_logs"); private static final TestsDataset SAMPLE_DATA = new TestsDataset("sample_data"); @@ -93,14 +95,13 @@ public class CsvTestsDataLoader { private static final TestsDataset BOOKS = new TestsDataset("books"); private static final TestsDataset SEMANTIC_TEXT = new TestsDataset("semantic_text").withInferenceEndpoint(true); - private static final String LOOKUP_INDEX_SUFFIX = "_lookup"; - public static final Map CSV_DATASET_MAP = Map.ofEntries( Map.entry(EMPLOYEES.indexName, EMPLOYEES), Map.entry(HOSTS.indexName, HOSTS), Map.entry(APPS.indexName, APPS), Map.entry(APPS_SHORT.indexName, APPS_SHORT), Map.entry(LANGUAGES.indexName, LANGUAGES), + Map.entry(LANGUAGES_LOOKUP.indexName, LANGUAGES_LOOKUP), Map.entry(UL_LOGS.indexName, UL_LOGS), Map.entry(SAMPLE_DATA.indexName, SAMPLE_DATA), Map.entry(ALERTS.indexName, ALERTS), @@ -130,9 +131,7 @@ public class CsvTestsDataLoader { Map.entry(DISTANCES.indexName, DISTANCES), Map.entry(ADDRESSES.indexName, ADDRESSES), Map.entry(BOOKS.indexName, BOOKS), - Map.entry(SEMANTIC_TEXT.indexName, SEMANTIC_TEXT), - // JOIN LOOKUP alias - Map.entry(LANGUAGES.indexName + LOOKUP_INDEX_SUFFIX, LANGUAGES.withIndex(LANGUAGES.indexName + LOOKUP_INDEX_SUFFIX)) + Map.entry(SEMANTIC_TEXT.indexName, SEMANTIC_TEXT) ); private static final EnrichConfig LANGUAGES_ENRICH = new EnrichConfig("languages_policy", "enrich-policy-languages.json"); diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/languages_lookup-settings.json b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/languages_lookup-settings.json new file mode 100644 index 0000000000000..b73d1f9accf92 --- /dev/null +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/languages_lookup-settings.json @@ -0,0 +1,5 @@ +{ + "index": { + "mode": "lookup" + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java index 7ad4c3d3e644d..dde7bc09ac615 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Analyzer.java @@ -62,6 +62,7 @@ import org.elasticsearch.xpack.esql.expression.predicate.operator.arithmetic.EsqlArithmeticOperation; import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.In; import org.elasticsearch.xpack.esql.index.EsIndex; +import org.elasticsearch.xpack.esql.index.IndexResolution; import org.elasticsearch.xpack.esql.parser.ParsingException; import org.elasticsearch.xpack.esql.plan.TableIdentifier; import org.elasticsearch.xpack.esql.plan.logical.Aggregate; @@ -106,7 +107,6 @@ import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Set; import java.util.function.Function; @@ -199,11 +199,12 @@ private static class ResolveTable extends ParameterizedAnalyzerRule"), enrichResolution); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java index 9630a520e8654..25bb6d80d0dd0 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/session/EsqlSession.java @@ -12,6 +12,7 @@ import org.elasticsearch.action.search.ShardSearchFailure; import org.elasticsearch.action.support.IndicesOptions; import org.elasticsearch.common.Strings; +import org.elasticsearch.common.TriFunction; import org.elasticsearch.common.collect.Iterators; import org.elasticsearch.common.regex.Regex; import org.elasticsearch.compute.data.Block; @@ -62,6 +63,8 @@ import org.elasticsearch.xpack.esql.plan.logical.RegexExtract; import org.elasticsearch.xpack.esql.plan.logical.UnresolvedRelation; import org.elasticsearch.xpack.esql.plan.logical.join.InlineJoin; +import org.elasticsearch.xpack.esql.plan.logical.join.JoinTypes; +import org.elasticsearch.xpack.esql.plan.logical.join.LookupJoin; import org.elasticsearch.xpack.esql.plan.logical.local.LocalRelation; import org.elasticsearch.xpack.esql.plan.logical.local.LocalSupplier; import org.elasticsearch.xpack.esql.plan.physical.EstimatesRowSize; @@ -76,7 +79,6 @@ import java.util.List; import java.util.Map; import java.util.Set; -import java.util.function.BiFunction; import java.util.function.Predicate; import java.util.stream.Collectors; @@ -272,9 +274,12 @@ public void analyzedPlan(LogicalPlan parsed, EsqlExecutionInfo executionInfo, Ac return; } - preAnalyze(parsed, executionInfo, (indices, policies) -> { + preAnalyze(parsed, executionInfo, (indices, lookupIndices, policies) -> { planningMetrics.gatherPreAnalysisMetrics(parsed); - Analyzer analyzer = new Analyzer(new AnalyzerContext(configuration, functionRegistry, indices, policies), verifier); + Analyzer analyzer = new Analyzer( + new AnalyzerContext(configuration, functionRegistry, indices, lookupIndices, policies), + verifier + ); var plan = analyzer.analyze(parsed); plan.setAnalyzed(); LOGGER.debug("Analyzed plan:\n{}", plan); @@ -285,7 +290,7 @@ public void analyzedPlan(LogicalPlan parsed, EsqlExecutionInfo executionInfo, Ac private void preAnalyze( LogicalPlan parsed, EsqlExecutionInfo executionInfo, - BiFunction action, + TriFunction action, ActionListener listener ) { PreAnalyzer.PreAnalysis preAnalysis = preAnalyzer.preAnalyze(parsed); @@ -299,63 +304,81 @@ private void preAnalyze( ).keySet(); enrichPolicyResolver.resolvePolicies(targetClusters, unresolvedPolicies, listener.delegateFailureAndWrap((l, enrichResolution) -> { // first we need the match_fields names from enrich policies and THEN, with an updated list of fields, we call field_caps API - var matchFields = enrichResolution.resolvedEnrichPolicies() + var enrichMatchFields = enrichResolution.resolvedEnrichPolicies() .stream() .map(ResolvedEnrichPolicy::matchField) .collect(Collectors.toSet()); - Map unavailableClusters = enrichResolution.getUnavailableClusters(); - preAnalyzeIndices(parsed, executionInfo, unavailableClusters, l.delegateFailureAndWrap((ll, indexResolution) -> { - // TODO in follow-PR (for skip_unavailble handling of missing concrete indexes) add some tests for invalid index - // resolution to updateExecutionInfo - if (indexResolution.isValid()) { - EsqlSessionCCSUtils.updateExecutionInfoWithClustersWithNoMatchingIndices(executionInfo, indexResolution); - EsqlSessionCCSUtils.updateExecutionInfoWithUnavailableClusters(executionInfo, indexResolution.unavailableClusters()); - if (executionInfo.isCrossClusterSearch() - && executionInfo.getClusterStateCount(EsqlExecutionInfo.Cluster.Status.RUNNING) == 0) { - // for a CCS, if all clusters have been marked as SKIPPED, nothing to search so send a sentinel - // Exception to let the LogicalPlanActionListener decide how to proceed - ll.onFailure(new NoClustersToSearchException()); - return; - } - - Set newClusters = enrichPolicyResolver.groupIndicesPerCluster( - indexResolution.get().concreteIndices().toArray(String[]::new) - ).keySet(); - // If new clusters appear when resolving the main indices, we need to resolve the enrich policies again - // or exclude main concrete indices. Since this is rare, it's simpler to resolve the enrich policies again. - // TODO: add a test for this - if (targetClusters.containsAll(newClusters) == false - // do not bother with a re-resolution if only remotes were requested and all were offline - && executionInfo.getClusterStateCount(EsqlExecutionInfo.Cluster.Status.RUNNING) > 0) { - enrichPolicyResolver.resolvePolicies( - newClusters, - unresolvedPolicies, - ll.map(newEnrichResolution -> action.apply(indexResolution, newEnrichResolution)) - ); - return; - } - } - ll.onResponse(action.apply(indexResolution, enrichResolution)); - }), matchFields); + // get the field names from the parsed plan combined with the ENRICH match fields from the ENRICH policy + var fieldNames = fieldNames(parsed, enrichMatchFields); + // First resolve the lookup indices, then the main indices + preAnalyzeLookupIndices( + preAnalysis.lookupIndices, + fieldNames, + l.delegateFailureAndWrap( + (lx, lookupIndexResolution) -> preAnalyzeIndices( + indices, + executionInfo, + enrichResolution.getUnavailableClusters(), + fieldNames, + lx.delegateFailureAndWrap((ll, indexResolution) -> { + // TODO in follow-PR (for skip_unavailble handling of missing concrete indexes) add some tests for invalid + // index resolution to updateExecutionInfo + if (indexResolution.isValid()) { + EsqlSessionCCSUtils.updateExecutionInfoWithClustersWithNoMatchingIndices(executionInfo, indexResolution); + EsqlSessionCCSUtils.updateExecutionInfoWithUnavailableClusters( + executionInfo, + indexResolution.unavailableClusters() + ); + if (executionInfo.isCrossClusterSearch() + && executionInfo.getClusterStateCount(EsqlExecutionInfo.Cluster.Status.RUNNING) == 0) { + // for a CCS, if all clusters have been marked as SKIPPED, nothing to search so send a sentinel + // Exception to let the LogicalPlanActionListener decide how to proceed + ll.onFailure(new NoClustersToSearchException()); + return; + } + + Set newClusters = enrichPolicyResolver.groupIndicesPerCluster( + indexResolution.get().concreteIndices().toArray(String[]::new) + ).keySet(); + // If new clusters appear when resolving the main indices, we need to resolve the enrich policies again + // or exclude main concrete indices. Since this is rare, it's simpler to resolve the enrich policies + // again. + // TODO: add a test for this + if (targetClusters.containsAll(newClusters) == false + // do not bother with a re-resolution if only remotes were requested and all were offline + && executionInfo.getClusterStateCount(EsqlExecutionInfo.Cluster.Status.RUNNING) > 0) { + enrichPolicyResolver.resolvePolicies( + newClusters, + unresolvedPolicies, + ll.map( + newEnrichResolution -> action.apply(indexResolution, lookupIndexResolution, newEnrichResolution) + ) + ); + return; + } + } + ll.onResponse(action.apply(indexResolution, lookupIndexResolution, enrichResolution)); + }) + ) + ) + ); })); } private void preAnalyzeIndices( - LogicalPlan parsed, + List indices, EsqlExecutionInfo executionInfo, Map unavailableClusters, // known to be unavailable from the enrich policy API call - ActionListener listener, - Set enrichPolicyMatchFields + Set fieldNames, + ActionListener listener ) { - PreAnalyzer.PreAnalysis preAnalysis = new PreAnalyzer().preAnalyze(parsed); // TODO we plan to support joins in the future when possible, but for now we'll just fail early if we see one - if (preAnalysis.indices.size() > 1) { + if (indices.size() > 1) { // Note: JOINs are not supported but we detect them when listener.onFailure(new MappingException("Queries with multiple indices are not supported")); - } else if (preAnalysis.indices.size() == 1) { - TableInfo tableInfo = preAnalysis.indices.get(0); + } else if (indices.size() == 1) { + TableInfo tableInfo = indices.get(0); TableIdentifier table = tableInfo.id(); - var fieldNames = fieldNames(parsed, enrichPolicyMatchFields); Map clusterIndices = indicesExpressionGrouper.groupIndices(IndicesOptions.DEFAULT, table.index()); for (Map.Entry entry : clusterIndices.entrySet()) { @@ -401,6 +424,25 @@ private void preAnalyzeIndices( } } + private void preAnalyzeLookupIndices(List indices, Set fieldNames, ActionListener listener) { + if (indices.size() > 1) { + // Note: JOINs on more than one index are not yet supported + listener.onFailure(new MappingException("More than one LOOKUP JOIN is not supported")); + } else if (indices.size() == 1) { + TableInfo tableInfo = indices.get(0); + TableIdentifier table = tableInfo.id(); + // call the EsqlResolveFieldsAction (field-caps) to resolve indices and get field types + indexResolver.resolveAsMergedMapping(table.index(), fieldNames, listener); + } else { + try { + // No lookup indices specified + listener.onResponse(IndexResolution.invalid("[none specified]")); + } catch (Exception ex) { + listener.onFailure(ex); + } + } + } + static Set fieldNames(LogicalPlan parsed, Set enrichPolicyMatchFields) { if (false == parsed.anyMatch(plan -> plan instanceof Aggregate || plan instanceof Project)) { // no explicit columns selection, for example "from employees" @@ -422,6 +464,7 @@ static Set fieldNames(LogicalPlan parsed, Set enrichPolicyMatchF // "keep" attributes are special whenever a wildcard is used in their name // ie "from test | eval lang = languages + 1 | keep *l" should consider both "languages" and "*l" as valid fields to ask for AttributeSet keepCommandReferences = new AttributeSet(); + AttributeSet keepJoinReferences = new AttributeSet(); List> keepMatches = new ArrayList<>(); List keepPatterns = new ArrayList<>(); @@ -440,6 +483,11 @@ static Set fieldNames(LogicalPlan parsed, Set enrichPolicyMatchF // The exact name of the field will be added later as part of enrichPolicyMatchFields Set enrichRefs.removeIf(attr -> attr instanceof EmptyAttribute); references.addAll(enrichRefs); + } else if (p instanceof LookupJoin join) { + keepJoinReferences.addAll(join.config().matchFields()); // TODO: why is this empty + if (join.config().type() instanceof JoinTypes.UsingJoinType usingJoinType) { + keepJoinReferences.addAll(usingJoinType.columns()); + } } else { references.addAll(p.references()); if (p instanceof UnresolvedRelation ur && ur.indexMode() == IndexMode.TIME_SERIES) { @@ -473,6 +521,8 @@ static Set fieldNames(LogicalPlan parsed, Set enrichPolicyMatchF references.removeIf(attr -> matchByName(attr, alias.name(), keepCommandReferences.contains(attr))); }); }); + // Add JOIN ON column references afterward to avoid Alias removal + references.addAll(keepJoinReferences); // remove valid metadata attributes because they will be filtered out by the IndexResolver anyway // otherwise, in some edge cases, we will fail to ask for "*" (all fields) instead From 3896de6639f1807676345d71b70b4cc218f9f37b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Cea=20Fontenla?= Date: Mon, 25 Nov 2024 12:34:20 +0100 Subject: [PATCH 09/34] ESQL: Fix AttributeSet#add() returning the opposite expected value (#117367) Set/Collection#add() is supposed to return `true` if the collection changed (If it actually added something). In this case, it must return if the old value is null. Extracted from https://github.com/elastic/elasticsearch/pull/114317 (Where it's being used) --- .../elasticsearch/xpack/esql/core/expression/AttributeSet.java | 2 +- .../org/elasticsearch/xpack/ql/expression/AttributeSet.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/AttributeSet.java b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/AttributeSet.java index e3eac60703915..a092e17931237 100644 --- a/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/AttributeSet.java +++ b/x-pack/plugin/esql-core/src/main/java/org/elasticsearch/xpack/esql/core/expression/AttributeSet.java @@ -113,7 +113,7 @@ public T[] toArray(T[] a) { @Override public boolean add(Attribute e) { - return delegate.put(e, PRESENT) != null; + return delegate.put(e, PRESENT) == null; } @Override diff --git a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/AttributeSet.java b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/AttributeSet.java index 0ee291af29ae1..a44764dab2a38 100644 --- a/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/AttributeSet.java +++ b/x-pack/plugin/ql/src/main/java/org/elasticsearch/xpack/ql/expression/AttributeSet.java @@ -113,7 +113,7 @@ public T[] toArray(T[] a) { @Override public boolean add(Attribute e) { - return delegate.put(e, PRESENT) != null; + return delegate.put(e, PRESENT) == null; } @Override From e319875d7e69d241283fc2e762cd6d8424886715 Mon Sep 17 00:00:00 2001 From: Ignacio Vera Date: Mon, 25 Nov 2024 13:27:38 +0100 Subject: [PATCH 10/34] Make InternalComposite.InternalBucket leaner (#117368) This commit removes reverseMuls and missingOrder from InternalComposite.InternalBucket . --- .../bucket/composite/CompositeAggregator.java | 10 +---- .../bucket/composite/InternalComposite.java | 45 ++++--------------- .../composite/InternalCompositeTests.java | 14 +----- 3 files changed, 11 insertions(+), 58 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/CompositeAggregator.java b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/CompositeAggregator.java index 0baecf6e3f92b..441b30f872a35 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/CompositeAggregator.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/CompositeAggregator.java @@ -205,15 +205,7 @@ public InternalAggregation[] buildAggregations(LongArray owningBucketOrds) throw CompositeKey key = queue.toCompositeKey(slot); InternalAggregations aggs = subAggsForBuckets.apply(slot); long docCount = queue.getDocCount(slot); - buckets[(int) queue.size()] = new InternalComposite.InternalBucket( - sourceNames, - formats, - key, - reverseMuls, - missingOrders, - docCount, - aggs - ); + buckets[(int) queue.size()] = new InternalComposite.InternalBucket(sourceNames, formats, key, docCount, aggs); } CompositeKey lastBucket = num > 0 ? buckets[num - 1].getRawKey() : null; return new InternalAggregation[] { diff --git a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/InternalComposite.java b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/InternalComposite.java index 8b3253418bc23..faa953e77edd8 100644 --- a/server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/InternalComposite.java +++ b/server/src/main/java/org/elasticsearch/search/aggregations/bucket/composite/InternalComposite.java @@ -19,7 +19,6 @@ import org.elasticsearch.search.aggregations.InternalAggregation; import org.elasticsearch.search.aggregations.InternalAggregations; import org.elasticsearch.search.aggregations.InternalMultiBucketAggregation; -import org.elasticsearch.search.aggregations.KeyComparable; import org.elasticsearch.search.aggregations.bucket.BucketReducer; import org.elasticsearch.search.aggregations.bucket.IteratorAndCurrent; import org.elasticsearch.search.aggregations.support.SamplingContext; @@ -103,7 +102,7 @@ public InternalComposite(StreamInput in) throws IOException { } this.reverseMuls = in.readIntArray(); this.missingOrders = in.readArray(MissingOrder::readFromStream, MissingOrder[]::new); - this.buckets = in.readCollectionAsList((input) -> new InternalBucket(input, sourceNames, formats, reverseMuls, missingOrders)); + this.buckets = in.readCollectionAsList((input) -> new InternalBucket(input, sourceNames, formats)); this.afterKey = in.readOptionalWriteable(CompositeKey::new); this.earlyTerminated = in.readBoolean(); } @@ -155,15 +154,7 @@ public InternalComposite create(List newBuckets) { @Override public InternalBucket createBucket(InternalAggregations aggregations, InternalBucket prototype) { - return new InternalBucket( - prototype.sourceNames, - prototype.formats, - prototype.key, - prototype.reverseMuls, - prototype.missingOrders, - prototype.docCount, - aggregations - ); + return new InternalBucket(prototype.sourceNames, prototype.formats, prototype.key, prototype.docCount, aggregations); } public int getSize() { @@ -206,7 +197,7 @@ protected AggregatorReducer getLeaderReducer(AggregationReduceContext reduceCont private final PriorityQueue> pq = new PriorityQueue<>(size) { @Override protected boolean lessThan(IteratorAndCurrent a, IteratorAndCurrent b) { - return a.current().compareKey(b.current()) < 0; + return a.current().compareKey(b.current(), reverseMuls, missingOrders) < 0; } }; private boolean earlyTerminated = false; @@ -227,7 +218,7 @@ public InternalAggregation get() { final List result = new ArrayList<>(); while (pq.size() > 0) { IteratorAndCurrent top = pq.top(); - if (lastBucket != null && top.current().compareKey(lastBucket) != 0) { + if (lastBucket != null && top.current().compareKey(lastBucket, reverseMuls, missingOrders) != 0) { InternalBucket reduceBucket = reduceBucket(buckets, reduceContext); buckets.clear(); result.add(reduceBucket); @@ -306,7 +297,7 @@ private InternalBucket reduceBucket(List buckets, AggregationRed final var reducedFormats = reducer.getProto().formats; final long docCount = reducer.getDocCount(); final InternalAggregations aggs = reducer.getAggregations(); - return new InternalBucket(sourceNames, reducedFormats, reducer.getProto().key, reverseMuls, missingOrders, docCount, aggs); + return new InternalBucket(sourceNames, reducedFormats, reducer.getProto().key, docCount, aggs); } } @@ -329,16 +320,11 @@ public int hashCode() { return Objects.hash(super.hashCode(), size, buckets, afterKey, Arrays.hashCode(reverseMuls), Arrays.hashCode(missingOrders)); } - public static class InternalBucket extends InternalMultiBucketAggregation.InternalBucket - implements - CompositeAggregation.Bucket, - KeyComparable { + public static class InternalBucket extends InternalMultiBucketAggregation.InternalBucket implements CompositeAggregation.Bucket { private final CompositeKey key; private final long docCount; private final InternalAggregations aggregations; - private final transient int[] reverseMuls; - private final transient MissingOrder[] missingOrders; private final transient List sourceNames; private final transient List formats; @@ -346,32 +332,20 @@ public static class InternalBucket extends InternalMultiBucketAggregation.Intern List sourceNames, List formats, CompositeKey key, - int[] reverseMuls, - MissingOrder[] missingOrders, long docCount, InternalAggregations aggregations ) { this.key = key; this.docCount = docCount; this.aggregations = aggregations; - this.reverseMuls = reverseMuls; - this.missingOrders = missingOrders; this.sourceNames = sourceNames; this.formats = formats; } - InternalBucket( - StreamInput in, - List sourceNames, - List formats, - int[] reverseMuls, - MissingOrder[] missingOrders - ) throws IOException { + InternalBucket(StreamInput in, List sourceNames, List formats) throws IOException { this.key = new CompositeKey(in); this.docCount = in.readVLong(); this.aggregations = InternalAggregations.readFrom(in); - this.reverseMuls = reverseMuls; - this.missingOrders = missingOrders; this.sourceNames = sourceNames; this.formats = formats; } @@ -444,8 +418,7 @@ List getFormats() { return formats; } - @Override - public int compareKey(InternalBucket other) { + int compareKey(InternalBucket other, int[] reverseMuls, MissingOrder[] missingOrders) { for (int i = 0; i < key.size(); i++) { if (key.get(i) == null) { if (other.key.get(i) == null) { @@ -470,8 +443,6 @@ InternalBucket finalizeSampling(SamplingContext samplingContext) { sourceNames, formats, key, - reverseMuls, - missingOrders, samplingContext.scaleUp(docCount), InternalAggregations.finalizeSampling(aggregations, samplingContext) ); diff --git a/server/src/test/java/org/elasticsearch/search/aggregations/bucket/composite/InternalCompositeTests.java b/server/src/test/java/org/elasticsearch/search/aggregations/bucket/composite/InternalCompositeTests.java index 5fb1d0e760afa..7e7ccb1d72e80 100644 --- a/server/src/test/java/org/elasticsearch/search/aggregations/bucket/composite/InternalCompositeTests.java +++ b/server/src/test/java/org/elasticsearch/search/aggregations/bucket/composite/InternalCompositeTests.java @@ -143,18 +143,10 @@ protected InternalComposite createTestInstance(String name, Map continue; } keys.add(key); - InternalComposite.InternalBucket bucket = new InternalComposite.InternalBucket( - sourceNames, - formats, - key, - reverseMuls, - missingOrders, - 1L, - aggregations - ); + InternalComposite.InternalBucket bucket = new InternalComposite.InternalBucket(sourceNames, formats, key, 1L, aggregations); buckets.add(bucket); } - Collections.sort(buckets, (o1, o2) -> o1.compareKey(o2)); + Collections.sort(buckets, (o1, o2) -> o1.compareKey(o2, reverseMuls, missingOrders)); CompositeKey lastBucket = buckets.size() > 0 ? buckets.get(buckets.size() - 1).getRawKey() : null; return new InternalComposite( name, @@ -191,8 +183,6 @@ protected InternalComposite mutateInstance(InternalComposite instance) { sourceNames, formats, createCompositeKey(), - reverseMuls, - missingOrders, randomLongBetween(1, 100), InternalAggregations.EMPTY ) From 339e4310814cd545339d5a8380f3d3de3479b461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Istv=C3=A1n=20Zolt=C3=A1n=20Szab=C3=B3?= Date: Mon, 25 Nov 2024 14:07:30 +0100 Subject: [PATCH 11/34] [DOCS] Documents that ELSER is the default service for `semantic_text` (#115769) --- .../mapping/types/semantic-text.asciidoc | 24 +++++++- .../semantic-search-semantic-text.asciidoc | 59 +++---------------- 2 files changed, 31 insertions(+), 52 deletions(-) diff --git a/docs/reference/mapping/types/semantic-text.asciidoc b/docs/reference/mapping/types/semantic-text.asciidoc index 684ad7c369e7d..f76a9352c2fe8 100644 --- a/docs/reference/mapping/types/semantic-text.asciidoc +++ b/docs/reference/mapping/types/semantic-text.asciidoc @@ -13,25 +13,45 @@ Long passages are <> to smaller secti The `semantic_text` field type specifies an inference endpoint identifier that will be used to generate embeddings. You can create the inference endpoint by using the <>. This field type and the <> type make it simpler to perform semantic search on your data. +If you don't specify an inference endpoint, the <> is used by default. Using `semantic_text`, you won't need to specify how to generate embeddings for your data, or how to index it. The {infer} endpoint automatically determines the embedding generation, indexing, and query to use. +If you use the ELSER service, you can set up `semantic_text` with the following API request: + [source,console] ------------------------------------------------------------ PUT my-index-000001 +{ + "mappings": { + "properties": { + "inference_field": { + "type": "semantic_text" + } + } + } +} +------------------------------------------------------------ + +If you use a service other than ELSER, you must create an {infer} endpoint using the <> and reference it when setting up `semantic_text` as the following example demonstrates: + +[source,console] +------------------------------------------------------------ +PUT my-index-000002 { "mappings": { "properties": { "inference_field": { "type": "semantic_text", - "inference_id": "my-elser-endpoint" + "inference_id": "my-openai-endpoint" <1> } } } } ------------------------------------------------------------ // TEST[skip:Requires inference endpoint] +<1> The `inference_id` of the {infer} endpoint to use to generate embeddings. The recommended way to use semantic_text is by having dedicated {infer} endpoints for ingestion and search. @@ -40,7 +60,7 @@ After creating dedicated {infer} endpoints for both, you can reference them usin [source,console] ------------------------------------------------------------ -PUT my-index-000002 +PUT my-index-000003 { "mappings": { "properties": { diff --git a/docs/reference/search/search-your-data/semantic-search-semantic-text.asciidoc b/docs/reference/search/search-your-data/semantic-search-semantic-text.asciidoc index 60692c19c184a..ba9c81db21384 100644 --- a/docs/reference/search/search-your-data/semantic-search-semantic-text.asciidoc +++ b/docs/reference/search/search-your-data/semantic-search-semantic-text.asciidoc @@ -21,45 +21,9 @@ This tutorial uses the <> for demonstra [[semantic-text-requirements]] ==== Requirements -To use the `semantic_text` field type, you must have an {infer} endpoint deployed in -your cluster using the <>. +This tutorial uses the <> for demonstration, which is created automatically as needed. +To use the `semantic_text` field type with an {infer} service other than ELSER, you must create an inference endpoint using the <>. -[discrete] -[[semantic-text-infer-endpoint]] -==== Create the {infer} endpoint - -Create an inference endpoint by using the <>: - -[source,console] ------------------------------------------------------------- -PUT _inference/sparse_embedding/my-elser-endpoint <1> -{ - "service": "elser", <2> - "service_settings": { - "adaptive_allocations": { <3> - "enabled": true, - "min_number_of_allocations": 3, - "max_number_of_allocations": 10 - }, - "num_threads": 1 - } -} ------------------------------------------------------------- -// TEST[skip:TBD] -<1> The task type is `sparse_embedding` in the path as the `elser` service will -be used and ELSER creates sparse vectors. The `inference_id` is -`my-elser-endpoint`. -<2> The `elser` service is used in this example. -<3> This setting enables and configures {ml-docs}/ml-nlp-auto-scale.html#nlp-model-adaptive-allocations[adaptive allocations]. -Adaptive allocations make it possible for ELSER to automatically scale up or down resources based on the current load on the process. - -[NOTE] -==== -You might see a 502 bad gateway error in the response when using the {kib} Console. -This error usually just reflects a timeout, while the model downloads in the background. -You can check the download progress in the {ml-app} UI. -If using the Python client, you can set the `timeout` parameter to a higher value. -==== [discrete] [[semantic-text-index-mapping]] @@ -75,8 +39,7 @@ PUT semantic-embeddings "mappings": { "properties": { "content": { <1> - "type": "semantic_text", <2> - "inference_id": "my-elser-endpoint" <3> + "type": "semantic_text" <2> } } } @@ -85,18 +48,14 @@ PUT semantic-embeddings // TEST[skip:TBD] <1> The name of the field to contain the generated embeddings. <2> The field to contain the embeddings is a `semantic_text` field. -<3> The `inference_id` is the inference endpoint you created in the previous step. -It will be used to generate the embeddings based on the input text. -Every time you ingest data into the related `semantic_text` field, this endpoint will be used for creating the vector representation of the text. +Since no `inference_id` is provided, the <> is used by default. +To use a different {infer} service, you must create an {infer} endpoint first using the <> and then specify it in the `semantic_text` field mapping using the `inference_id` parameter. [NOTE] ==== -If you're using web crawlers or connectors to generate indices, you have to -<> for these indices to -include the `semantic_text` field. Once the mapping is updated, you'll need to run -a full web crawl or a full connector sync. This ensures that all existing -documents are reprocessed and updated with the new semantic embeddings, -enabling semantic search on the updated data. +If you're using web crawlers or connectors to generate indices, you have to <> for these indices to include the `semantic_text` field. +Once the mapping is updated, you'll need to run a full web crawl or a full connector sync. +This ensures that all existing documents are reprocessed and updated with the new semantic embeddings, enabling semantic search on the updated data. ==== @@ -288,4 +247,4 @@ query from the `semantic-embedding` index: * If you want to use `semantic_text` in hybrid search, refer to https://colab.research.google.com/github/elastic/elasticsearch-labs/blob/main/notebooks/search/09-semantic-text.ipynb[this notebook] for a step-by-step guide. * For more information on how to optimize your ELSER endpoints, refer to {ml-docs}/ml-nlp-elser.html#elser-recommendations[the ELSER recommendations] section in the model documentation. -* To learn more about model autoscaling, refer to the {ml-docs}/ml-nlp-auto-scale.html[trained model autoscaling] page. \ No newline at end of file +* To learn more about model autoscaling, refer to the {ml-docs}/ml-nlp-auto-scale.html[trained model autoscaling] page. From 86098f8c7f83368a1b6f50ffdef4e9c8eb8583b0 Mon Sep 17 00:00:00 2001 From: Mike Pellegrini Date: Mon, 25 Nov 2024 08:09:37 -0500 Subject: [PATCH 12/34] Mute default ELSER tests (#117390) --- muted-tests.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/muted-tests.yml b/muted-tests.yml index d4b77f5269c10..ff19d7d59da75 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -223,6 +223,12 @@ tests: - class: org.elasticsearch.xpack.inference.DefaultEndPointsIT method: testInferDeploysDefaultElser issue: https://github.com/elastic/elasticsearch/issues/114913 +- class: org.elasticsearch.xpack.inference.InferenceRestIT + method: test {p0=inference/40_semantic_text_query/Query a field that uses the default ELSER 2 endpoint} + issue: https://github.com/elastic/elasticsearch/issues/117027 +- class: org.elasticsearch.xpack.inference.InferenceRestIT + method: test {p0=inference/30_semantic_text_inference/Calculates embeddings using the default ELSER 2 endpoint} + issue: https://github.com/elastic/elasticsearch/issues/117349 - class: org.elasticsearch.xpack.security.operator.OperatorPrivilegesIT method: testEveryActionIsEitherOperatorOnlyOrNonOperator issue: https://github.com/elastic/elasticsearch/issues/102992 From 105d4f89a6e0f3b663c2fbb99939408e53e9c1c0 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine <58790826+elasticsearchmachine@users.noreply.github.com> Date: Tue, 26 Nov 2024 00:19:00 +1100 Subject: [PATCH 13/34] Mute org.elasticsearch.xpack.test.rest.XPackRestIT test {p0=transform/transforms_reset/Test reset running transform} #117473 --- muted-tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/muted-tests.yml b/muted-tests.yml index ff19d7d59da75..da8a093ebe674 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -232,6 +232,9 @@ tests: - class: org.elasticsearch.xpack.security.operator.OperatorPrivilegesIT method: testEveryActionIsEitherOperatorOnlyOrNonOperator issue: https://github.com/elastic/elasticsearch/issues/102992 +- class: org.elasticsearch.xpack.test.rest.XPackRestIT + method: test {p0=transform/transforms_reset/Test reset running transform} + issue: https://github.com/elastic/elasticsearch/issues/117473 # Examples: # From ff58d891a168078c99334204081ef95607f8d48f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20FOUCRET?= Date: Mon, 25 Nov 2024 14:22:11 +0100 Subject: [PATCH 14/34] ES|QL kql function. (#116764) --- .../esql/functions/description/kql.asciidoc | 5 + .../esql/functions/examples/kql.asciidoc | 13 ++ .../esql/functions/kibana/definition/kql.json | 37 ++++ .../esql/functions/kibana/docs/kql.md | 14 ++ .../esql/functions/layout/kql.asciidoc | 17 ++ .../esql/functions/parameters/kql.asciidoc | 6 + .../esql/functions/signature/kql.svg | 1 + .../esql/functions/types/kql.asciidoc | 10 + x-pack/plugin/esql/build.gradle | 2 + .../src/main/resources/kql-function.csv-spec | 153 +++++++++++++++ .../src/main/resources/qstr-function.csv-spec | 10 +- .../xpack/esql/plugin/KqlFunctionIT.java | 144 ++++++++++++++ .../xpack/esql/action/EsqlCapabilities.java | 5 + .../xpack/esql/analysis/Verifier.java | 22 ++- .../function/EsqlFunctionRegistry.java | 2 + .../function/fulltext/FullTextWritables.java | 16 +- .../expression/function/fulltext/Kql.java | 73 +++++++ .../physical/local/PushFiltersToSource.java | 6 +- .../planner/EsqlExpressionTranslators.java | 10 + .../xpack/esql/querydsl/query/KqlQuery.java | 85 ++++++++ .../elasticsearch/xpack/esql/CsvTests.java | 4 + .../xpack/esql/analysis/VerifierTests.java | 89 +++++++++ .../function/fulltext/KqlTests.java | 41 ++++ .../NoneFieldFullTextFunctionTestCase.java | 62 ++++++ .../function/fulltext/QueryStringTests.java | 43 +--- .../LocalPhysicalPlanOptimizerTests.java | 184 +++++++++++++++++- .../esql/querydsl/query/KqlQueryTests.java | 139 +++++++++++++ .../xpack/kql/query/KqlQueryBuilder.java | 20 +- .../rest-api-spec/test/esql/60_usage.yml | 2 +- 29 files changed, 1149 insertions(+), 66 deletions(-) create mode 100644 docs/reference/esql/functions/description/kql.asciidoc create mode 100644 docs/reference/esql/functions/examples/kql.asciidoc create mode 100644 docs/reference/esql/functions/kibana/definition/kql.json create mode 100644 docs/reference/esql/functions/kibana/docs/kql.md create mode 100644 docs/reference/esql/functions/layout/kql.asciidoc create mode 100644 docs/reference/esql/functions/parameters/kql.asciidoc create mode 100644 docs/reference/esql/functions/signature/kql.svg create mode 100644 docs/reference/esql/functions/types/kql.asciidoc create mode 100644 x-pack/plugin/esql/qa/testFixtures/src/main/resources/kql-function.csv-spec create mode 100644 x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/KqlFunctionIT.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Kql.java create mode 100644 x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/KqlQuery.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/KqlTests.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/NoneFieldFullTextFunctionTestCase.java create mode 100644 x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/querydsl/query/KqlQueryTests.java diff --git a/docs/reference/esql/functions/description/kql.asciidoc b/docs/reference/esql/functions/description/kql.asciidoc new file mode 100644 index 0000000000000..e1fe411e6689c --- /dev/null +++ b/docs/reference/esql/functions/description/kql.asciidoc @@ -0,0 +1,5 @@ +// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +*Description* + +Performs a KQL query. Returns true if the provided KQL query string matches the row. diff --git a/docs/reference/esql/functions/examples/kql.asciidoc b/docs/reference/esql/functions/examples/kql.asciidoc new file mode 100644 index 0000000000000..1f8518aeec394 --- /dev/null +++ b/docs/reference/esql/functions/examples/kql.asciidoc @@ -0,0 +1,13 @@ +// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +*Example* + +[source.merge.styled,esql] +---- +include::{esql-specs}/kql-function.csv-spec[tag=kql-with-field] +---- +[%header.monospaced.styled,format=dsv,separator=|] +|=== +include::{esql-specs}/kql-function.csv-spec[tag=kql-with-field-result] +|=== + diff --git a/docs/reference/esql/functions/kibana/definition/kql.json b/docs/reference/esql/functions/kibana/definition/kql.json new file mode 100644 index 0000000000000..6960681fbbf0d --- /dev/null +++ b/docs/reference/esql/functions/kibana/definition/kql.json @@ -0,0 +1,37 @@ +{ + "comment" : "This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it.", + "type" : "eval", + "name" : "kql", + "description" : "Performs a KQL query. Returns true if the provided KQL query string matches the row.", + "signatures" : [ + { + "params" : [ + { + "name" : "query", + "type" : "keyword", + "optional" : false, + "description" : "Query string in KQL query string format." + } + ], + "variadic" : false, + "returnType" : "boolean" + }, + { + "params" : [ + { + "name" : "query", + "type" : "text", + "optional" : false, + "description" : "Query string in KQL query string format." + } + ], + "variadic" : false, + "returnType" : "boolean" + } + ], + "examples" : [ + "FROM books \n| WHERE KQL(\"author: Faulkner\")\n| KEEP book_no, author \n| SORT book_no \n| LIMIT 5;" + ], + "preview" : true, + "snapshot_only" : true +} diff --git a/docs/reference/esql/functions/kibana/docs/kql.md b/docs/reference/esql/functions/kibana/docs/kql.md new file mode 100644 index 0000000000000..0ba419c1cd032 --- /dev/null +++ b/docs/reference/esql/functions/kibana/docs/kql.md @@ -0,0 +1,14 @@ + + +### KQL +Performs a KQL query. Returns true if the provided KQL query string matches the row. + +``` +FROM books +| WHERE KQL("author: Faulkner") +| KEEP book_no, author +| SORT book_no +| LIMIT 5; +``` diff --git a/docs/reference/esql/functions/layout/kql.asciidoc b/docs/reference/esql/functions/layout/kql.asciidoc new file mode 100644 index 0000000000000..8cf2687b240c1 --- /dev/null +++ b/docs/reference/esql/functions/layout/kql.asciidoc @@ -0,0 +1,17 @@ +// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +[discrete] +[[esql-kql]] +=== `KQL` + +preview::["Do not use on production environments. This functionality is in technical preview and may be changed or removed in a future release. Elastic will work to fix any issues, but features in technical preview are not subject to the support SLA of official GA features."] + +*Syntax* + +[.text-center] +image::esql/functions/signature/kql.svg[Embedded,opts=inline] + +include::../parameters/kql.asciidoc[] +include::../description/kql.asciidoc[] +include::../types/kql.asciidoc[] +include::../examples/kql.asciidoc[] diff --git a/docs/reference/esql/functions/parameters/kql.asciidoc b/docs/reference/esql/functions/parameters/kql.asciidoc new file mode 100644 index 0000000000000..6fb69323ff73c --- /dev/null +++ b/docs/reference/esql/functions/parameters/kql.asciidoc @@ -0,0 +1,6 @@ +// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +*Parameters* + +`query`:: +Query string in KQL query string format. diff --git a/docs/reference/esql/functions/signature/kql.svg b/docs/reference/esql/functions/signature/kql.svg new file mode 100644 index 0000000000000..3f550f27ccdff --- /dev/null +++ b/docs/reference/esql/functions/signature/kql.svg @@ -0,0 +1 @@ +KQL(query) \ No newline at end of file diff --git a/docs/reference/esql/functions/types/kql.asciidoc b/docs/reference/esql/functions/types/kql.asciidoc new file mode 100644 index 0000000000000..866a39e925665 --- /dev/null +++ b/docs/reference/esql/functions/types/kql.asciidoc @@ -0,0 +1,10 @@ +// This is generated by ESQL's AbstractFunctionTestCase. Do no edit it. See ../README.md for how to regenerate it. + +*Supported types* + +[%header.monospaced.styled,format=dsv,separator=|] +|=== +query | result +keyword | boolean +text | boolean +|=== diff --git a/x-pack/plugin/esql/build.gradle b/x-pack/plugin/esql/build.gradle index f92c895cc5b7b..02f9752d21e09 100644 --- a/x-pack/plugin/esql/build.gradle +++ b/x-pack/plugin/esql/build.gradle @@ -34,6 +34,7 @@ dependencies { compileOnly project(':modules:lang-painless:spi') compileOnly project(xpackModule('esql-core')) compileOnly project(xpackModule('ml')) + implementation project(xpackModule('kql')) implementation project('compute') implementation project('compute:ann') implementation project(':libs:dissect') @@ -50,6 +51,7 @@ dependencies { testImplementation(testArtifact(project(xpackModule('core')))) testImplementation project(path: xpackModule('enrich')) testImplementation project(path: xpackModule('spatial')) + testImplementation project(path: xpackModule('kql')) testImplementation project(path: ':modules:reindex') testImplementation project(path: ':modules:parent-join') diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/kql-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/kql-function.csv-spec new file mode 100644 index 0000000000000..02be58efac774 --- /dev/null +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/kql-function.csv-spec @@ -0,0 +1,153 @@ +############################################### +# Tests for KQL function +# + +kqlWithField +required_capability: kql_function + +// tag::kql-with-field[] +FROM books +| WHERE KQL("author: Faulkner") +| KEEP book_no, author +| SORT book_no +| LIMIT 5; +// end::kql-with-field[] + +// tag::kql-with-field-result[] +book_no:keyword | author:text +2378 | [Carol Faulkner, Holly Byers Ochoa, Lucretia Mott] +2713 | William Faulkner +2847 | Colleen Faulkner +2883 | William Faulkner +3293 | Danny Faulkner +; +// end::kql-with-field-result[] + +kqlWithMultipleFields +required_capability: kql_function + +from books +| where kql("title:Return* AND author:*Tolkien") +| keep book_no, title; +ignoreOrder:true + +book_no:keyword | title:text +2714 | Return of the King Being the Third Part of The Lord of the Rings +7350 | Return of the Shadow +; + +kqlWithQueryExpressions +required_capability: kql_function + +from books +| where kql(CONCAT("title:Return*", " AND author:*Tolkien")) +| keep book_no, title; +ignoreOrder:true + +book_no:keyword | title:text +2714 | Return of the King Being the Third Part of The Lord of the Rings +7350 | Return of the Shadow +; + +kqlWithConjunction +required_capability: kql_function + +from books +| where kql("title: Rings") and ratings > 4.6 +| keep book_no, title; +ignoreOrder:true + +book_no:keyword | title:text +4023 | A Tolkien Compass: Including J. R. R. Tolkien's Guide to the Names in The Lord of the Rings +7140 | The Lord of the Rings Poster Collection: Six Paintings by Alan Lee (No. 1) +; + +kqlWithFunctionPushedToLucene +required_capability: kql_function + +from hosts +| where kql("host: beta") and cidr_match(ip1, "127.0.0.2/32", "127.0.0.3/32") +| keep card, host, ip0, ip1; +ignoreOrder:true + +card:keyword |host:keyword |ip0:ip |ip1:ip +eth1 |beta |127.0.0.1 |127.0.0.2 +; + +kqlWithNonPushableConjunction +required_capability: kql_function + +from books +| where kql("title: Rings") and length(title) > 75 +| keep book_no, title; +ignoreOrder:true + +book_no:keyword | title:text +4023 |A Tolkien Compass: Including J. R. R. Tolkien's Guide to the Names in The Lord of the Rings +; + +kqlWithMultipleWhereClauses +required_capability: kql_function + +from books +| where kql("title: rings") +| where kql("year > 1 AND year < 2005") +| keep book_no, title; +ignoreOrder:true + +book_no:keyword | title:text +4023 | A Tolkien Compass: Including J. R. R. Tolkien's Guide to the Names in The Lord of the Rings +7140 | The Lord of the Rings Poster Collection: Six Paintings by Alan Lee (No. 1) +; + + +kqlWithMultivaluedTextField +required_capability: kql_function + +from employees +| where kql("job_positions: Tech Lead AND job_positions:(Reporting Analyst)") +| keep emp_no, first_name, last_name; +ignoreOrder:true + +emp_no:integer | first_name:keyword | last_name:keyword +10004 | Chirstian | Koblick +10010 | Duangkaew | Piveteau +10011 | Mary | Sluis +10088 | Jungsoon | Syrzycki +10093 | Sailaja | Desikan +10097 | Remzi | Waschkowski +; + +kqlWithMultivaluedNumericField +required_capability: kql_function + +from employees +| where kql("salary_change > 14") +| keep emp_no, first_name, last_name, salary_change; +ignoreOrder:true + +emp_no:integer | first_name:keyword | last_name:keyword | salary_change:double +10003 | Parto | Bamford | [12.82, 14.68] +10015 | Guoxiang | Nooteboom | [12.4, 14.25] +10023 | Bojan | Montemayor | [0.8, 14.63] +10040 | Weiyi | Meriste | [-8.94, 1.92, 6.97, 14.74] +10061 | Tse | Herber | [-2.58, -0.95, 14.39] +10065 | Satosi | Awdeh | [-9.81, -1.47, 14.44] +10099 | Valter | Sullins | [-8.78, -3.98, 10.71, 14.26] +; + +testMultiValuedFieldWithConjunction +required_capability: kql_function + +from employees +| where (kql("job_positions: (Data Scientist) OR job_positions:(Support Engineer)")) and gender == "F" +| keep emp_no, first_name, last_name; +ignoreOrder:true + +emp_no:integer | first_name:keyword | last_name:keyword +10023 | Bojan | Montemayor +10041 | Uri | Lenart +10044 | Mingsen | Casley +10053 | Sanjiv | Zschoche +10069 | Margareta | Bierman +; diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/qstr-function.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/qstr-function.csv-spec index 3e92e55928d64..6039dc05b6c44 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/qstr-function.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/qstr-function.csv-spec @@ -101,8 +101,8 @@ book_no:keyword | title:text ; -matchMultivaluedTextField -required_capability: match_function +qstrWithMultivaluedTextField +required_capability: qstr_function from employees | where qstr("job_positions: (Tech Lead) AND job_positions:(Reporting Analyst)") @@ -118,8 +118,8 @@ emp_no:integer | first_name:keyword | last_name:keyword 10097 | Remzi | Waschkowski ; -matchMultivaluedNumericField -required_capability: match_function +qstrWithMultivaluedNumericField +required_capability: qstr_function from employees | where qstr("salary_change: [14 TO *]") @@ -137,7 +137,7 @@ emp_no:integer | first_name:keyword | last_name:keyword | salary_change:double ; testMultiValuedFieldWithConjunction -required_capability: match_function +required_capability: qstr_function from employees | where (qstr("job_positions: (Data Scientist) OR job_positions:(Support Engineer)")) and gender == "F" diff --git a/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/KqlFunctionIT.java b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/KqlFunctionIT.java new file mode 100644 index 0000000000000..d58637ab52c86 --- /dev/null +++ b/x-pack/plugin/esql/src/internalClusterTest/java/org/elasticsearch/xpack/esql/plugin/KqlFunctionIT.java @@ -0,0 +1,144 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.plugin; + +import org.elasticsearch.action.index.IndexRequest; +import org.elasticsearch.action.support.WriteRequest; +import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.query.QueryShardException; +import org.elasticsearch.xpack.esql.VerificationException; +import org.elasticsearch.xpack.esql.action.AbstractEsqlIntegTestCase; +import org.elasticsearch.xpack.esql.action.EsqlCapabilities; +import org.junit.Before; +import org.junit.BeforeClass; + +import java.util.List; + +import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked; +import static org.hamcrest.CoreMatchers.containsString; + +public class KqlFunctionIT extends AbstractEsqlIntegTestCase { + + @BeforeClass + protected static void ensureKqlFunctionEnabled() { + assumeTrue("kql function capability not available", EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()); + } + + @Before + public void setupIndex() { + createAndPopulateIndex(); + } + + public void testSimpleKqlQuery() { + var query = """ + FROM test + | WHERE kql("content: dog") + | KEEP id + | SORT id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id")); + assertColumnTypes(resp.columns(), List.of("integer")); + assertValues(resp.values(), List.of(List.of(1), List.of(3), List.of(4), List.of(5))); + } + } + + public void testMultiFieldKqlQuery() { + var query = """ + FROM test + | WHERE kql("dog OR canine") + | KEEP id + """; + + try (var resp = run(query)) { + assertColumnNames(resp.columns(), List.of("id")); + assertColumnTypes(resp.columns(), List.of("integer")); + assertValuesInAnyOrder(resp.values(), List.of(List.of(1), List.of(2), List.of(3), List.of(4), List.of(5))); + } + } + + public void testKqlQueryWithinEval() { + var query = """ + FROM test + | EVAL matches_query = kql("title: fox") + """; + + var error = expectThrows(VerificationException.class, () -> run(query)); + assertThat(error.getMessage(), containsString("[KQL] function is only supported in WHERE commands")); + } + + public void testInvalidKqlQueryEof() { + var query = """ + FROM test + | WHERE kql("content: ((((dog") + """; + + var error = expectThrows(QueryShardException.class, () -> run(query)); + assertThat(error.getMessage(), containsString("Failed to parse KQL query [content: ((((dog]")); + assertThat(error.getRootCause().getMessage(), containsString("line 1:11: mismatched input '('")); + } + + public void testInvalidKqlQueryLexicalError() { + var query = """ + FROM test + | WHERE kql(":") + """; + + var error = expectThrows(QueryShardException.class, () -> run(query)); + assertThat(error.getMessage(), containsString("Failed to parse KQL query [:]")); + assertThat(error.getRootCause().getMessage(), containsString("line 1:1: extraneous input ':' ")); + } + + private void createAndPopulateIndex() { + var indexName = "test"; + var client = client().admin().indices(); + var CreateRequest = client.prepareCreate(indexName) + .setSettings(Settings.builder().put("index.number_of_shards", 1)) + .setMapping("id", "type=integer", "content", "type=text"); + assertAcked(CreateRequest); + client().prepareBulk() + .add( + new IndexRequest(indexName).id("1") + .source("id", 1, "content", "The quick brown animal swiftly jumps over a lazy dog", "title", "A Swift Fox's Journey") + ) + .add( + new IndexRequest(indexName).id("2") + .source("id", 2, "content", "A speedy brown fox hops effortlessly over a sluggish canine", "title", "The Fox's Leap") + ) + .add( + new IndexRequest(indexName).id("3") + .source("id", 3, "content", "Quick and nimble, the fox vaults over the lazy dog", "title", "Brown Fox in Action") + ) + .add( + new IndexRequest(indexName).id("4") + .source( + "id", + 4, + "content", + "A fox that is quick and brown jumps over a dog that is quite lazy", + "title", + "Speedy Animals" + ) + ) + .add( + new IndexRequest(indexName).id("5") + .source( + "id", + 5, + "content", + "With agility, a quick brown fox bounds over a slow-moving dog", + "title", + "Foxes and Canines" + ) + ) + .setRefreshPolicy(WriteRequest.RefreshPolicy.IMMEDIATE) + .get(); + ensureYellow(indexName); + } +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index d675f772b5a3b..d9ce7fca312b3 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -415,6 +415,11 @@ public enum Cap { */ MATCH_FUNCTION, + /** + * KQL function + */ + KQL_FUNCTION(Build.current().isSnapshot()), + /** * Don't optimize CASE IS NOT NULL function by not requiring the fields to be not null as well. * https://github.com/elastic/elasticsearch/issues/112704 diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Verifier.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Verifier.java index 3ebb52641232e..2be13398dab2f 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Verifier.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/analysis/Verifier.java @@ -34,6 +34,7 @@ import org.elasticsearch.xpack.esql.expression.function.aggregate.FilteredExpression; import org.elasticsearch.xpack.esql.expression.function.aggregate.Rate; import org.elasticsearch.xpack.esql.expression.function.fulltext.FullTextFunction; +import org.elasticsearch.xpack.esql.expression.function.fulltext.Kql; import org.elasticsearch.xpack.esql.expression.function.fulltext.Match; import org.elasticsearch.xpack.esql.expression.function.fulltext.QueryString; import org.elasticsearch.xpack.esql.expression.function.grouping.Categorize; @@ -793,14 +794,19 @@ private static void checkNotPresentInDisjunctions( private static void checkFullTextQueryFunctions(LogicalPlan plan, Set failures) { if (plan instanceof Filter f) { Expression condition = f.condition(); - checkCommandsBeforeExpression( - plan, - condition, - QueryString.class, - lp -> (lp instanceof Filter || lp instanceof OrderBy || lp instanceof EsRelation), - qsf -> "[" + qsf.functionName() + "] " + qsf.functionType(), - failures - ); + + List.of(QueryString.class, Kql.class).forEach(functionClass -> { + // Check for limitations of QSTR and KQL function. + checkCommandsBeforeExpression( + plan, + condition, + functionClass, + lp -> (lp instanceof Filter || lp instanceof OrderBy || lp instanceof EsRelation), + fullTextFunction -> "[" + fullTextFunction.functionName() + "] " + fullTextFunction.functionType(), + failures + ); + }); + checkCommandsBeforeExpression( plan, condition, diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java index ea1669ccc7a4f..3d26bc170b723 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/EsqlFunctionRegistry.java @@ -33,6 +33,7 @@ import org.elasticsearch.xpack.esql.expression.function.aggregate.Top; import org.elasticsearch.xpack.esql.expression.function.aggregate.Values; import org.elasticsearch.xpack.esql.expression.function.aggregate.WeightedAvg; +import org.elasticsearch.xpack.esql.expression.function.fulltext.Kql; import org.elasticsearch.xpack.esql.expression.function.fulltext.Match; import org.elasticsearch.xpack.esql.expression.function.fulltext.QueryString; import org.elasticsearch.xpack.esql.expression.function.grouping.Bucket; @@ -411,6 +412,7 @@ private static FunctionDefinition[][] snapshotFunctions() { // This is an experimental function and can be removed without notice. def(Delay.class, Delay::new, "delay"), def(Categorize.class, Categorize::new, "categorize"), + def(Kql.class, Kql::new, "kql"), def(Rate.class, Rate::withUnresolvedTimestamp, "rate") } }; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java index d59c736783172..8804a031de78c 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/FullTextWritables.java @@ -8,14 +8,28 @@ package org.elasticsearch.xpack.esql.expression.function.fulltext; import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.xpack.esql.action.EsqlCapabilities; import org.elasticsearch.xpack.esql.core.expression.predicate.fulltext.MatchQueryPredicate; import org.elasticsearch.xpack.esql.core.expression.predicate.fulltext.MultiMatchQueryPredicate; +import java.util.ArrayList; +import java.util.Collections; import java.util.List; public class FullTextWritables { public static List getNamedWriteables() { - return List.of(MatchQueryPredicate.ENTRY, MultiMatchQueryPredicate.ENTRY, QueryString.ENTRY, Match.ENTRY); + List entries = new ArrayList<>(); + + entries.add(MatchQueryPredicate.ENTRY); + entries.add(MultiMatchQueryPredicate.ENTRY); + entries.add(QueryString.ENTRY); + entries.add(Match.ENTRY); + + if (EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()) { + entries.add(Kql.ENTRY); + } + + return Collections.unmodifiableList(entries); } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Kql.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Kql.java new file mode 100644 index 0000000000000..c03902373c02e --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/fulltext/Kql.java @@ -0,0 +1,73 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.fulltext; + +import org.elasticsearch.common.io.stream.NamedWriteableRegistry; +import org.elasticsearch.common.io.stream.StreamInput; +import org.elasticsearch.common.io.stream.StreamOutput; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.NodeInfo; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.Example; +import org.elasticsearch.xpack.esql.expression.function.FunctionInfo; +import org.elasticsearch.xpack.esql.expression.function.Param; +import org.elasticsearch.xpack.esql.io.stream.PlanStreamInput; +import org.elasticsearch.xpack.esql.querydsl.query.KqlQuery; + +import java.io.IOException; +import java.util.List; + +/** + * Full text function that performs a {@link KqlQuery} . + */ +public class Kql extends FullTextFunction { + public static final NamedWriteableRegistry.Entry ENTRY = new NamedWriteableRegistry.Entry(Expression.class, "Kql", Kql::new); + + @FunctionInfo( + returnType = "boolean", + preview = true, + description = "Performs a KQL query. Returns true if the provided KQL query string matches the row.", + examples = { @Example(file = "kql-function", tag = "kql-with-field") } + ) + public Kql( + Source source, + @Param( + name = "query", + type = { "keyword", "text" }, + description = "Query string in KQL query string format." + ) Expression queryString + ) { + super(source, queryString, List.of(queryString)); + } + + private Kql(StreamInput in) throws IOException { + this(Source.readFrom((PlanStreamInput) in), in.readNamedWriteable(Expression.class)); + } + + @Override + public void writeTo(StreamOutput out) throws IOException { + source().writeTo(out); + out.writeNamedWriteable(query()); + } + + @Override + public String getWriteableName() { + return ENTRY.name; + } + + @Override + public Expression replaceChildren(List newChildren) { + return new Kql(source(), newChildren.get(0)); + } + + @Override + protected NodeInfo info() { + return NodeInfo.create(this, Kql::new, query()); + } + +} diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/PushFiltersToSource.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/PushFiltersToSource.java index 9f574ee8005b2..3d6c35e914294 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/PushFiltersToSource.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/optimizer/rules/physical/local/PushFiltersToSource.java @@ -30,8 +30,8 @@ import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.core.util.CollectionUtils; import org.elasticsearch.xpack.esql.core.util.Queries; +import org.elasticsearch.xpack.esql.expression.function.fulltext.FullTextFunction; import org.elasticsearch.xpack.esql.expression.function.fulltext.Match; -import org.elasticsearch.xpack.esql.expression.function.fulltext.QueryString; import org.elasticsearch.xpack.esql.expression.function.scalar.ip.CIDRMatch; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.BinarySpatialFunction; import org.elasticsearch.xpack.esql.expression.function.scalar.spatial.SpatialRelatesFunction; @@ -252,10 +252,10 @@ static boolean canPushToSource(Expression exp, LucenePushdownPredicates lucenePu && Expressions.foldable(cidrMatch.matches()); } else if (exp instanceof SpatialRelatesFunction spatial) { return canPushSpatialFunctionToSource(spatial, lucenePushdownPredicates); - } else if (exp instanceof QueryString) { - return true; } else if (exp instanceof Match mf) { return mf.field() instanceof FieldAttribute && DataType.isString(mf.field().dataType()); + } else if (exp instanceof FullTextFunction) { + return true; } return false; } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsqlExpressionTranslators.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsqlExpressionTranslators.java index 6fac7bab2bd80..1580b77931240 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsqlExpressionTranslators.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/EsqlExpressionTranslators.java @@ -34,6 +34,7 @@ import org.elasticsearch.xpack.esql.core.tree.Source; import org.elasticsearch.xpack.esql.core.type.DataType; import org.elasticsearch.xpack.esql.core.util.Check; +import org.elasticsearch.xpack.esql.expression.function.fulltext.Kql; import org.elasticsearch.xpack.esql.expression.function.fulltext.Match; import org.elasticsearch.xpack.esql.expression.function.fulltext.QueryString; import org.elasticsearch.xpack.esql.expression.function.scalar.ip.CIDRMatch; @@ -47,6 +48,7 @@ import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.LessThan; import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.LessThanOrEqual; import org.elasticsearch.xpack.esql.expression.predicate.operator.comparison.NotEquals; +import org.elasticsearch.xpack.esql.querydsl.query.KqlQuery; import org.elasticsearch.xpack.esql.querydsl.query.SpatialRelatesQuery; import org.elasticsearch.xpack.versionfield.Version; @@ -89,6 +91,7 @@ public final class EsqlExpressionTranslators { new ExpressionTranslators.MultiMatches(), new MatchFunctionTranslator(), new QueryStringFunctionTranslator(), + new KqlFunctionTranslator(), new Scalars() ); @@ -538,4 +541,11 @@ protected Query asQuery(QueryString queryString, TranslatorHandler handler) { return new QueryStringQuery(queryString.source(), queryString.queryAsText(), Map.of(), Map.of()); } } + + public static class KqlFunctionTranslator extends ExpressionTranslator { + @Override + protected Query asQuery(Kql kqlFunction, TranslatorHandler handler) { + return new KqlQuery(kqlFunction.source(), kqlFunction.queryAsText()); + } + } } diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/KqlQuery.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/KqlQuery.java new file mode 100644 index 0000000000000..c388a131b9ab6 --- /dev/null +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/querydsl/query/KqlQuery.java @@ -0,0 +1,85 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +package org.elasticsearch.xpack.esql.querydsl.query; + +import org.elasticsearch.core.Booleans; +import org.elasticsearch.index.query.QueryBuilder; +import org.elasticsearch.xpack.esql.core.querydsl.query.Query; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.kql.query.KqlQueryBuilder; + +import java.util.Collections; +import java.util.Map; +import java.util.Objects; +import java.util.function.BiConsumer; + +import static java.util.Map.entry; + +public class KqlQuery extends Query { + + private static final Map> BUILDER_APPLIERS = Map.ofEntries( + entry(KqlQueryBuilder.TIME_ZONE_FIELD.getPreferredName(), KqlQueryBuilder::timeZone), + entry(KqlQueryBuilder.DEFAULT_FIELD_FIELD.getPreferredName(), KqlQueryBuilder::defaultField), + entry(KqlQueryBuilder.CASE_INSENSITIVE_FIELD.getPreferredName(), (qb, s) -> qb.caseInsensitive(Booleans.parseBoolean(s))) + ); + + private final String query; + + private final Map options; + + // dedicated constructor for QueryTranslator + public KqlQuery(Source source, String query) { + this(source, query, null); + } + + public KqlQuery(Source source, String query, Map options) { + super(source); + this.query = query; + this.options = options == null ? Collections.emptyMap() : options; + } + + @Override + public QueryBuilder asBuilder() { + final KqlQueryBuilder queryBuilder = new KqlQueryBuilder(query); + options.forEach((k, v) -> { + if (BUILDER_APPLIERS.containsKey(k)) { + BUILDER_APPLIERS.get(k).accept(queryBuilder, v); + } else { + throw new IllegalArgumentException("illegal kql query option [" + k + "]"); + } + }); + return queryBuilder; + } + + public String query() { + return query; + } + + public Map options() { + return options; + } + + @Override + public int hashCode() { + return Objects.hash(query, options); + } + + @Override + public boolean equals(Object obj) { + if (false == super.equals(obj)) { + return false; + } + + KqlQuery other = (KqlQuery) obj; + return Objects.equals(query, other.query) && Objects.equals(options, other.options); + } + + @Override + protected String innerToString() { + return query; + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java index 012720db9efd9..010a60ef7da15 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/CsvTests.java @@ -257,6 +257,10 @@ public final void test() throws Throwable { "can't use MATCH function in csv tests", testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.MATCH_FUNCTION.capabilityName()) ); + assumeFalse( + "can't use KQL function in csv tests", + testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.KQL_FUNCTION.capabilityName()) + ); assumeFalse( "lookup join disabled for csv tests", testCase.requiredCapabilities.contains(EsqlCapabilities.Cap.JOIN_LOOKUP.capabilityName()) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java index 7b2f85b80b3b6..f25b19c4e5d1c 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/analysis/VerifierTests.java @@ -1263,11 +1263,74 @@ public void testQueryStringFunctionsNotAllowedAfterCommands() throws Exception { ); } + public void testKqlFunctionsNotAllowedAfterCommands() throws Exception { + // Skip test if the kql function is not enabled. + assumeTrue("kql function capability not available", EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()); + + // Source commands + assertEquals("1:13: [KQL] function cannot be used after SHOW", error("show info | where kql(\"8.16.0\")")); + assertEquals("1:17: [KQL] function cannot be used after ROW", error("row a= \"Anna\" | where kql(\"Anna\")")); + + // Processing commands + assertEquals( + "1:43: [KQL] function cannot be used after DISSECT", + error("from test | dissect first_name \"%{foo}\" | where kql(\"Connection\")") + ); + assertEquals("1:27: [KQL] function cannot be used after DROP", error("from test | drop emp_no | where kql(\"Anna\")")); + assertEquals( + "1:71: [KQL] function cannot be used after ENRICH", + error("from test | enrich languages on languages with lang = language_name | where kql(\"Anna\")") + ); + assertEquals("1:26: [KQL] function cannot be used after EVAL", error("from test | eval z = 2 | where kql(\"Anna\")")); + assertEquals( + "1:44: [KQL] function cannot be used after GROK", + error("from test | grok last_name \"%{WORD:foo}\" | where kql(\"Anna\")") + ); + assertEquals("1:27: [KQL] function cannot be used after KEEP", error("from test | keep emp_no | where kql(\"Anna\")")); + assertEquals("1:24: [KQL] function cannot be used after LIMIT", error("from test | limit 10 | where kql(\"Anna\")")); + assertEquals("1:35: [KQL] function cannot be used after MV_EXPAND", error("from test | mv_expand last_name | where kql(\"Anna\")")); + assertEquals( + "1:45: [KQL] function cannot be used after RENAME", + error("from test | rename last_name as full_name | where kql(\"Anna\")") + ); + assertEquals( + "1:52: [KQL] function cannot be used after STATS", + error("from test | STATS c = COUNT(emp_no) BY languages | where kql(\"Anna\")") + ); + + // Some combination of processing commands + assertEquals("1:38: [KQL] function cannot be used after LIMIT", error("from test | keep emp_no | limit 10 | where kql(\"Anna\")")); + assertEquals( + "1:46: [KQL] function cannot be used after MV_EXPAND", + error("from test | limit 10 | mv_expand last_name | where kql(\"Anna\")") + ); + assertEquals( + "1:52: [KQL] function cannot be used after KEEP", + error("from test | mv_expand last_name | keep last_name | where kql(\"Anna\")") + ); + assertEquals( + "1:77: [KQL] function cannot be used after RENAME", + error("from test | STATS c = COUNT(emp_no) BY languages | rename c as total_emps | where kql(\"Anna\")") + ); + assertEquals( + "1:54: [KQL] function cannot be used after DROP", + error("from test | rename last_name as name | drop emp_no | where kql(\"Anna\")") + ); + } + public void testQueryStringFunctionOnlyAllowedInWhere() throws Exception { assertEquals("1:9: [QSTR] function is only supported in WHERE commands", error("row a = qstr(\"Anna\")")); checkFullTextFunctionsOnlyAllowedInWhere("QSTR", "qstr(\"Anna\")", "function"); } + public void testKqlFunctionOnlyAllowedInWhere() throws Exception { + // Skip test if the kql function is not enabled. + assumeTrue("kql function capability not available", EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()); + + assertEquals("1:9: [KQL] function is only supported in WHERE commands", error("row a = kql(\"Anna\")")); + checkFullTextFunctionsOnlyAllowedInWhere("KQL", "kql(\"Anna\")", "function"); + } + public void testMatchFunctionOnlyAllowedInWhere() throws Exception { checkFullTextFunctionsOnlyAllowedInWhere("MATCH", "match(first_name, \"Anna\")", "function"); } @@ -1309,10 +1372,29 @@ public void testQueryStringFunctionArgNotNullOrConstant() throws Exception { // Other value types are tested in QueryStringFunctionTests } + public void testKqlFunctionArgNotNullOrConstant() throws Exception { + // Skip test if the kql function is not enabled. + assumeTrue("kql function capability not available", EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()); + + assertEquals( + "1:19: argument of [kql(first_name)] must be a constant, received [first_name]", + error("from test | where kql(first_name)") + ); + assertEquals("1:19: argument of [kql(null)] cannot be null, received [null]", error("from test | where kql(null)")); + // Other value types are tested in KqlFunctionTests + } + public void testQueryStringWithDisjunctions() { checkWithDisjunctions("QSTR", "qstr(\"first_name: Anna\")", "function"); } + public void testKqlFunctionWithDisjunctions() { + // Skip test if the kql function is not enabled. + assumeTrue("kql function capability not available", EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()); + + checkWithDisjunctions("KQL", "kql(\"first_name: Anna\")", "function"); + } + public void testMatchFunctionWithDisjunctions() { checkWithDisjunctions("MATCH", "match(first_name, \"Anna\")", "function"); } @@ -1368,6 +1450,13 @@ public void testQueryStringFunctionWithNonBooleanFunctions() { checkFullTextFunctionsWithNonBooleanFunctions("QSTR", "qstr(\"first_name: Anna\")", "function"); } + public void testKqlFunctionWithNonBooleanFunctions() { + // Skip test if the kql function is not enabled. + assumeTrue("kql function capability not available", EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()); + + checkFullTextFunctionsWithNonBooleanFunctions("KQL", "kql(\"first_name: Anna\")", "function"); + } + public void testMatchFunctionWithNonBooleanFunctions() { checkFullTextFunctionsWithNonBooleanFunctions("MATCH", "match(first_name, \"Anna\")", "function"); } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/KqlTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/KqlTests.java new file mode 100644 index 0000000000000..d97be6b169eef --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/KqlTests.java @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.fulltext; + +import com.carrotsearch.randomizedtesting.annotations.Name; +import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; + +import org.elasticsearch.xpack.esql.action.EsqlCapabilities; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; +import org.junit.BeforeClass; + +import java.util.List; +import java.util.function.Supplier; + +public class KqlTests extends NoneFieldFullTextFunctionTestCase { + @BeforeClass + protected static void ensureKqlFunctionEnabled() { + assumeTrue("kql function capability not available", EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()); + } + + public KqlTests(@Name("TestCase") Supplier testCaseSupplier) { + super(testCaseSupplier); + } + + @ParametersFactory + public static Iterable parameters() { + return generateParameters(); + } + + @Override + protected Expression build(Source source, List args) { + return new Kql(source, args.get(0)); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/NoneFieldFullTextFunctionTestCase.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/NoneFieldFullTextFunctionTestCase.java new file mode 100644 index 0000000000000..383cb8671053d --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/NoneFieldFullTextFunctionTestCase.java @@ -0,0 +1,62 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +package org.elasticsearch.xpack.esql.expression.function.fulltext; + +import org.apache.lucene.util.BytesRef; +import org.elasticsearch.xpack.esql.core.expression.Expression; +import org.elasticsearch.xpack.esql.core.type.DataType; +import org.elasticsearch.xpack.esql.expression.function.AbstractFunctionTestCase; +import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; +import org.hamcrest.Matcher; + +import java.util.LinkedList; +import java.util.List; +import java.util.function.Supplier; + +import static org.hamcrest.Matchers.equalTo; + +public abstract class NoneFieldFullTextFunctionTestCase extends AbstractFunctionTestCase { + + public NoneFieldFullTextFunctionTestCase(Supplier testCaseSupplier) { + this.testCase = testCaseSupplier.get(); + } + + public final void testFold() { + Expression expression = buildLiteralExpression(testCase); + if (testCase.getExpectedTypeError() != null) { + assertTypeResolutionFailure(expression); + return; + } + assertFalse("expected resolved", expression.typeResolved().unresolved()); + } + + protected static Iterable generateParameters() { + List suppliers = new LinkedList<>(); + for (DataType strType : DataType.stringTypes()) { + suppliers.add( + new TestCaseSupplier( + "<" + strType + ">", + List.of(strType), + () -> testCase(strType, randomAlphaOfLengthBetween(1, 10), equalTo(true)) + ) + ); + } + List errorsSuppliers = errorsForCasesWithoutExamples(suppliers, (v, p) -> "string"); + // Don't test null, as it is not allowed but the expected message is not a type error - so we check it separately in VerifierTests + return parameterSuppliersFromTypedData(errorsSuppliers.stream().filter(s -> s.types().contains(DataType.NULL) == false).toList()); + } + + private static TestCaseSupplier.TestCase testCase(DataType strType, String str, Matcher matcher) { + return new TestCaseSupplier.TestCase( + List.of(new TestCaseSupplier.TypedData(new BytesRef(str), strType, "query")), + "EndsWithEvaluator[str=Attribute[channel=0], suffix=Attribute[channel=1]]", + DataType.BOOLEAN, + matcher + ); + } +} diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryStringTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryStringTests.java index b4b4ebcaacde6..f573e59ab205a 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryStringTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/fulltext/QueryStringTests.java @@ -10,61 +10,24 @@ import com.carrotsearch.randomizedtesting.annotations.Name; import com.carrotsearch.randomizedtesting.annotations.ParametersFactory; -import org.apache.lucene.util.BytesRef; import org.elasticsearch.xpack.esql.core.expression.Expression; import org.elasticsearch.xpack.esql.core.tree.Source; -import org.elasticsearch.xpack.esql.core.type.DataType; -import org.elasticsearch.xpack.esql.expression.function.AbstractFunctionTestCase; import org.elasticsearch.xpack.esql.expression.function.FunctionName; import org.elasticsearch.xpack.esql.expression.function.TestCaseSupplier; -import org.hamcrest.Matcher; -import java.util.LinkedList; import java.util.List; import java.util.function.Supplier; -import static org.hamcrest.Matchers.equalTo; - @FunctionName("qstr") -public class QueryStringTests extends AbstractFunctionTestCase { +public class QueryStringTests extends NoneFieldFullTextFunctionTestCase { public QueryStringTests(@Name("TestCase") Supplier testCaseSupplier) { - this.testCase = testCaseSupplier.get(); + super(testCaseSupplier); } @ParametersFactory public static Iterable parameters() { - List suppliers = new LinkedList<>(); - for (DataType strType : DataType.stringTypes()) { - suppliers.add( - new TestCaseSupplier( - "<" + strType + ">", - List.of(strType), - () -> testCase(strType, randomAlphaOfLengthBetween(1, 10), equalTo(true)) - ) - ); - } - List errorsSuppliers = errorsForCasesWithoutExamples(suppliers, (v, p) -> "string"); - // Don't test null, as it is not allowed but the expected message is not a type error - so we check it separately in VerifierTests - return parameterSuppliersFromTypedData(errorsSuppliers.stream().filter(s -> s.types().contains(DataType.NULL) == false).toList()); - } - - public final void testFold() { - Expression expression = buildLiteralExpression(testCase); - if (testCase.getExpectedTypeError() != null) { - assertTypeResolutionFailure(expression); - return; - } - assertFalse("expected resolved", expression.typeResolved().unresolved()); - } - - private static TestCaseSupplier.TestCase testCase(DataType strType, String str, Matcher matcher) { - return new TestCaseSupplier.TestCase( - List.of(new TestCaseSupplier.TypedData(new BytesRef(str), strType, "query")), - "EndsWithEvaluator[str=Attribute[channel=0], suffix=Attribute[channel=1]]", - DataType.BOOLEAN, - matcher - ); + return generateParameters(); } @Override diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java index 269b4806680a6..4612ccb425ba2 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/optimizer/LocalPhysicalPlanOptimizerTests.java @@ -26,6 +26,7 @@ import org.elasticsearch.xpack.core.enrich.EnrichPolicy; import org.elasticsearch.xpack.esql.EsqlTestUtils; import org.elasticsearch.xpack.esql.EsqlTestUtils.TestSearchStats; +import org.elasticsearch.xpack.esql.action.EsqlCapabilities; import org.elasticsearch.xpack.esql.analysis.Analyzer; import org.elasticsearch.xpack.esql.analysis.AnalyzerContext; import org.elasticsearch.xpack.esql.analysis.EnrichResolution; @@ -62,6 +63,7 @@ import org.elasticsearch.xpack.esql.stats.Metrics; import org.elasticsearch.xpack.esql.stats.SearchContextStats; import org.elasticsearch.xpack.esql.stats.SearchStats; +import org.elasticsearch.xpack.kql.query.KqlQueryBuilder; import org.junit.Before; import java.io.IOException; @@ -678,7 +680,7 @@ public void testMatchFunctionMultipleWhereClauses() { * \_EsQueryExec[test], indexMode[standard], query[{"bool":{"must":[{"match":{"last_name":{"query":"Smith"}}}, * {"match":{"first_name":{"query":"John"}}}],"boost":1.0}}][_doc{f}#14], limit[1000], sort[] estimatedRowSize[324] */ - public void testMatchFunctionMultipleQstrClauses() { + public void testMatchFunctionMultipleMatchClauses() { String queryText = """ from test | where match(last_name, "Smith") and match(first_name, "John") @@ -698,6 +700,182 @@ public void testMatchFunctionMultipleQstrClauses() { assertThat(query.query().toString(), is(expected.toString())); } + /** + * Expecting + * LimitExec[1000[INTEGER]] + * \_ExchangeExec[[_meta_field{f}#8, emp_no{f}#2, first_name{f}#3, gender{f}#4, job{f}#9, job.raw{f}#10, languages{f}#5, last_na + * me{f}#6, long_noidx{f}#11, salary{f}#7],false] + * \_ProjectExec[[_meta_field{f}#8, emp_no{f}#2, first_name{f}#3, gender{f}#4, job{f}#9, job.raw{f}#10, languages{f}#5, last_na + * me{f}#6, long_noidx{f}#11, salary{f}#7]] + * \_FieldExtractExec[_meta_field{f}#8, emp_no{f}#2, first_name{f}#3, gen] + * \_EsQueryExec[test], indexMode[standard], query[{"kql":{"query":"last_name: Smith"}}] + */ + public void testKqlFunction() { + // Skip test if the kql function is not enabled. + assumeTrue("kql function capability not available", EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()); + + var plan = plannerOptimizer.plan(""" + from test + | where kql("last_name: Smith") + """, IS_SV_STATS); + + var limit = as(plan, LimitExec.class); + var exchange = as(limit.child(), ExchangeExec.class); + var project = as(exchange.child(), ProjectExec.class); + var field = as(project.child(), FieldExtractExec.class); + var query = as(field.child(), EsQueryExec.class); + assertThat(query.limit().fold(), is(1000)); + var expected = kqlQueryBuilder("last_name: Smith"); + assertThat(query.query().toString(), is(expected.toString())); + } + + /** + * Expecting + * LimitExec[1000[INTEGER]] + * \_ExchangeExec[[_meta_field{f}#1419, emp_no{f}#1413, first_name{f}#1414, gender{f}#1415, job{f}#1420, job.raw{f}#1421, langua + * ges{f}#1416, last_name{f}#1417, long_noidx{f}#1422, salary{f}#1418],false] + * \_ProjectExec[[_meta_field{f}#1419, emp_no{f}#1413, first_name{f}#1414, gender{f}#1415, job{f}#1420, job.raw{f}#1421, langua + * ges{f}#1416, last_name{f}#1417, long_noidx{f}#1422, salary{f}#1418]] + * \_FieldExtractExec[_meta_field{f}#1419, emp_no{f}#1413, first_name{f}#] + * \_EsQueryExec[test], indexMode[standard], query[{"bool":{"must":[{"kql":{"query":"last_name: Smith"}} + * ,{"esql_single_value":{"field":"emp_no","next":{"range":{"emp_no":{"gt":10010,"boost":1.0}}},"source":"emp_no > 10010"}}], + * "boost":1.0}}][_doc{f}#1423], limit[1000], sort[] estimatedRowSize[324] + */ + public void testKqlFunctionConjunctionWhereOperands() { + // Skip test if the kql function is not enabled. + assumeTrue("kql function capability not available", EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()); + + String queryText = """ + from test + | where kql("last_name: Smith") and emp_no > 10010 + """; + var plan = plannerOptimizer.plan(queryText, IS_SV_STATS); + + var limit = as(plan, LimitExec.class); + var exchange = as(limit.child(), ExchangeExec.class); + var project = as(exchange.child(), ProjectExec.class); + var field = as(project.child(), FieldExtractExec.class); + var query = as(field.child(), EsQueryExec.class); + assertThat(query.limit().fold(), is(1000)); + + Source filterSource = new Source(2, 36, "emp_no > 10000"); + var range = wrapWithSingleQuery(queryText, QueryBuilders.rangeQuery("emp_no").gt(10010), "emp_no", filterSource); + var kqlQuery = kqlQueryBuilder("last_name: Smith"); + var expected = QueryBuilders.boolQuery().must(kqlQuery).must(range); + assertThat(query.query().toString(), is(expected.toString())); + } + + /** + * Expecting + * LimitExec[1000[INTEGER]] + * \_ExchangeExec[[!alias_integer, boolean{f}#4, byte{f}#5, constant_keyword-foo{f}#6, date{f}#7, double{f}#8, float{f}#9, half_ + * float{f}#10, integer{f}#12, ip{f}#13, keyword{f}#14, long{f}#15, scaled_float{f}#11, short{f}#17, text{f}#18, unsigned_long{f}#16], + * false] + * \_ProjectExec[[!alias_integer, boolean{f}#4, byte{f}#5, constant_keyword-foo{f}#6, date{f}#7, double{f}#8, float{f}#9, half_ + * float{f}#10, integer{f}#12, ip{f}#13, keyword{f}#14, long{f}#15, scaled_float{f}#11, short{f}#17, text{f}#18, unsigned_long{f}#16] + * \_FieldExtractExec[!alias_integer, boolean{f}#4, byte{f}#5, constant_k..] + * \_EsQueryExec[test], indexMode[standard], query[{"bool":{"must":[{"kql":{"query":"last_name: Smith"}},{ + * "esql_single_value":{"field":"ip","next":{"terms":{"ip":["127.0.0.1/32"],"boost":1.0}}, + * "source":"cidr_match(ip, \"127.0.0.1/32\")@2:38"}}],"boost":1.0}}][_doc{f}#21], limit[1000], sort[] estimatedRowSize[354] + */ + public void testKqlFunctionWithFunctionsPushedToLucene() { + // Skip test if the kql function is not enabled. + assumeTrue("kql function capability not available", EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()); + + String queryText = """ + from test + | where kql("last_name: Smith") and cidr_match(ip, "127.0.0.1/32") + """; + var analyzer = makeAnalyzer("mapping-all-types.json"); + var plan = plannerOptimizer.plan(queryText, IS_SV_STATS, analyzer); + + var limit = as(plan, LimitExec.class); + var exchange = as(limit.child(), ExchangeExec.class); + var project = as(exchange.child(), ProjectExec.class); + var field = as(project.child(), FieldExtractExec.class); + var query = as(field.child(), EsQueryExec.class); + assertThat(query.limit().fold(), is(1000)); + + Source filterSource = new Source(2, 36, "cidr_match(ip, \"127.0.0.1/32\")"); + var terms = wrapWithSingleQuery(queryText, QueryBuilders.termsQuery("ip", "127.0.0.1/32"), "ip", filterSource); + var kqlQuery = kqlQueryBuilder("last_name: Smith"); + var expected = QueryBuilders.boolQuery().must(kqlQuery).must(terms); + assertThat(query.query().toString(), is(expected.toString())); + } + + /** + * Expecting + * LimitExec[1000[INTEGER]] + * \_ExchangeExec[[_meta_field{f}#1163, emp_no{f}#1157, first_name{f}#1158, gender{f}#1159, job{f}#1164, job.raw{f}#1165, langua + * ges{f}#1160, last_name{f}#1161, long_noidx{f}#1166, salary{f}#1162],false] + * \_ProjectExec[[_meta_field{f}#1163, emp_no{f}#1157, first_name{f}#1158, gender{f}#1159, job{f}#1164, job.raw{f}#1165, langua + * ges{f}#1160, last_name{f}#1161, long_noidx{f}#1166, salary{f}#1162]] + * \_FieldExtractExec[_meta_field{f}#1163, emp_no{f}#1157, first_name{f}#] + * \_EsQueryExec[test], indexMode[standard], + * query[{"bool":{"must":[{"kql":{"query":"last_name: Smith"}}, + * {"esql_single_value":{"field":"emp_no","next":{"range":{"emp_no":{"gt":10010,"boost":1.0}}},"source":"emp_no > 10010@3:9"}}], + * "boost":1.0}}][_doc{f}#1167], limit[1000], sort[] estimatedRowSize[324] + */ + public void testKqlFunctionMultipleWhereClauses() { + // Skip test if the kql function is not enabled. + assumeTrue("kql function capability not available", EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()); + + String queryText = """ + from test + | where kql("last_name: Smith") + | where emp_no > 10010 + """; + var plan = plannerOptimizer.plan(queryText, IS_SV_STATS); + + var limit = as(plan, LimitExec.class); + var exchange = as(limit.child(), ExchangeExec.class); + var project = as(exchange.child(), ProjectExec.class); + var field = as(project.child(), FieldExtractExec.class); + var query = as(field.child(), EsQueryExec.class); + assertThat(query.limit().fold(), is(1000)); + + Source filterSource = new Source(3, 8, "emp_no > 10000"); + var range = wrapWithSingleQuery(queryText, QueryBuilders.rangeQuery("emp_no").gt(10010), "emp_no", filterSource); + var kqlQuery = kqlQueryBuilder("last_name: Smith"); + var expected = QueryBuilders.boolQuery().must(kqlQuery).must(range); + assertThat(query.query().toString(), is(expected.toString())); + } + + /** + * Expecting + * LimitExec[1000[INTEGER]] + * \_ExchangeExec[[_meta_field{f}#8, emp_no{f}#2, first_name{f}#3, gender{f}#4, job{f}#9, job.raw{f}#10, languages{f}#5, last_na + * me{f}#6, long_noidx{f}#11, salary{f}#7],false] + * \_ProjectExec[[_meta_field{f}#8, emp_no{f}#2, first_name{f}#3, gender{f}#4, job{f}#9, job.raw{f}#10, languages{f}#5, last_na + * me{f}#6, long_noidx{f}#11, salary{f}#7]] + * \_FieldExtractExec[_meta_field{f}#8, emp_no{f}#2, first_name{f}#3, gen] + * \_EsQueryExec[test], indexMode[standard], query[{"bool": {"must":[ + * {"kql":{"query":"last_name: Smith"}}, + * {"kql":{"query":"emp_no > 10010"}}],"boost":1.0}}] + */ + public void testKqlFunctionMultipleKqlClauses() { + // Skip test if the kql function is not enabled. + assumeTrue("kql function capability not available", EsqlCapabilities.Cap.KQL_FUNCTION.isEnabled()); + + String queryText = """ + from test + | where kql("last_name: Smith") and kql("emp_no > 10010") + """; + var plan = plannerOptimizer.plan(queryText, IS_SV_STATS); + + var limit = as(plan, LimitExec.class); + var exchange = as(limit.child(), ExchangeExec.class); + var project = as(exchange.child(), ProjectExec.class); + var field = as(project.child(), FieldExtractExec.class); + var query = as(field.child(), EsQueryExec.class); + assertThat(query.limit().fold(), is(1000)); + + var kqlQueryLeft = kqlQueryBuilder("last_name: Smith"); + var kqlQueryRight = kqlQueryBuilder("emp_no > 10010"); + var expected = QueryBuilders.boolQuery().must(kqlQueryLeft).must(kqlQueryRight); + assertThat(query.query().toString(), is(expected.toString())); + } + // optimizer doesn't know yet how to break down different multi count public void testCountFieldsAndAllWithFilter() { var plan = plannerOptimizer.plan(""" @@ -1166,4 +1344,8 @@ private Stat queryStatsFor(PhysicalPlan plan) { protected List filteredWarnings() { return withDefaultLimitWarning(super.filteredWarnings()); } + + private static KqlQueryBuilder kqlQueryBuilder(String query) { + return new KqlQueryBuilder(query); + } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/querydsl/query/KqlQueryTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/querydsl/query/KqlQueryTests.java new file mode 100644 index 0000000000000..8dfb50f84ac1e --- /dev/null +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/querydsl/query/KqlQueryTests.java @@ -0,0 +1,139 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +package org.elasticsearch.xpack.esql.querydsl.query; + +import org.elasticsearch.test.ESTestCase; +import org.elasticsearch.xpack.esql.core.tree.Source; +import org.elasticsearch.xpack.esql.core.tree.SourceTests; +import org.elasticsearch.xpack.esql.core.util.StringUtils; +import org.elasticsearch.xpack.kql.query.KqlQueryBuilder; + +import java.time.ZoneId; +import java.time.zone.ZoneRulesException; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import static org.elasticsearch.test.EqualsHashCodeTestUtils.checkEqualsAndHashCode; +import static org.hamcrest.Matchers.equalTo; + +public class KqlQueryTests extends ESTestCase { + static KqlQuery randomKqkQueryQuery() { + Map options = new HashMap<>(); + + if (randomBoolean()) { + options.put(KqlQueryBuilder.CASE_INSENSITIVE_FIELD.getPreferredName(), String.valueOf(randomBoolean())); + } + + if (randomBoolean()) { + options.put(KqlQueryBuilder.DEFAULT_FIELD_FIELD.getPreferredName(), randomIdentifier()); + } + + if (randomBoolean()) { + options.put(KqlQueryBuilder.TIME_ZONE_FIELD.getPreferredName(), randomZone().getId()); + } + + return new KqlQuery(SourceTests.randomSource(), randomAlphaOfLength(5), Collections.unmodifiableMap(options)); + } + + public void testEqualsAndHashCode() { + for (int runs = 0; runs < 100; runs++) { + checkEqualsAndHashCode(randomKqkQueryQuery(), KqlQueryTests::copy, KqlQueryTests::mutate); + } + } + + private static KqlQuery copy(KqlQuery query) { + return new KqlQuery(query.source(), query.query(), query.options()); + } + + private static KqlQuery mutate(KqlQuery query) { + List> options = Arrays.asList( + q -> new KqlQuery(SourceTests.mutate(q.source()), q.query(), q.options()), + q -> new KqlQuery(q.source(), randomValueOtherThan(q.query(), () -> randomAlphaOfLength(5)), q.options()), + q -> new KqlQuery(q.source(), q.query(), mutateOptions(q.options())) + ); + + return randomFrom(options).apply(query); + } + + private static Map mutateOptions(Map options) { + Map mutatedOptions = new HashMap<>(options); + if (options.isEmpty() == false && randomBoolean()) { + mutatedOptions = options.entrySet() + .stream() + .filter(entry -> randomBoolean()) + .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue)); + } + + while (mutatedOptions.equals(options)) { + if (randomBoolean()) { + mutatedOptions = mutateOption( + mutatedOptions, + KqlQueryBuilder.CASE_INSENSITIVE_FIELD.getPreferredName(), + () -> String.valueOf(randomBoolean()) + ); + } + + if (randomBoolean()) { + mutatedOptions = mutateOption( + mutatedOptions, + KqlQueryBuilder.DEFAULT_FIELD_FIELD.getPreferredName(), + () -> randomIdentifier() + ); + } + + if (randomBoolean()) { + mutatedOptions = mutateOption( + mutatedOptions, + KqlQueryBuilder.TIME_ZONE_FIELD.getPreferredName(), + () -> randomZone().getId() + ); + } + } + + return Collections.unmodifiableMap(mutatedOptions); + } + + private static Map mutateOption(Map options, String optionName, Supplier valueSupplier) { + options = new HashMap<>(options); + options.put(optionName, randomValueOtherThan(options.get(optionName), valueSupplier)); + return options; + } + + public void testQueryBuilding() { + KqlQueryBuilder qb = getBuilder(Map.of("case_insensitive", "false")); + assertThat(qb.caseInsensitive(), equalTo(false)); + + qb = getBuilder(Map.of("case_insensitive", "false", "time_zone", "UTC", "default_field", "foo")); + assertThat(qb.caseInsensitive(), equalTo(false)); + assertThat(qb.timeZone(), equalTo(ZoneId.of("UTC"))); + assertThat(qb.defaultField(), equalTo("foo")); + + Exception e = expectThrows(IllegalArgumentException.class, () -> getBuilder(Map.of("pizza", "yummy"))); + assertThat(e.getMessage(), equalTo("illegal kql query option [pizza]")); + + e = expectThrows(ZoneRulesException.class, () -> getBuilder(Map.of("time_zone", "aoeu"))); + assertThat(e.getMessage(), equalTo("Unknown time-zone ID: aoeu")); + } + + private static KqlQueryBuilder getBuilder(Map options) { + final Source source = new Source(1, 1, StringUtils.EMPTY); + final KqlQuery kqlQuery = new KqlQuery(source, "eggplant", options); + return (KqlQueryBuilder) kqlQuery.asBuilder(); + } + + public void testToString() { + final Source source = new Source(1, 1, StringUtils.EMPTY); + final KqlQuery kqlQuery = new KqlQuery(source, "eggplant", Map.of()); + assertEquals("KqlQuery@1:2[eggplant]", kqlQuery.toString()); + } +} diff --git a/x-pack/plugin/kql/src/main/java/org/elasticsearch/xpack/kql/query/KqlQueryBuilder.java b/x-pack/plugin/kql/src/main/java/org/elasticsearch/xpack/kql/query/KqlQueryBuilder.java index 5dff9126b6be4..e2817665d8f79 100644 --- a/x-pack/plugin/kql/src/main/java/org/elasticsearch/xpack/kql/query/KqlQueryBuilder.java +++ b/x-pack/plugin/kql/src/main/java/org/elasticsearch/xpack/kql/query/KqlQueryBuilder.java @@ -17,6 +17,7 @@ import org.elasticsearch.index.query.AbstractQueryBuilder; import org.elasticsearch.index.query.QueryBuilder; import org.elasticsearch.index.query.QueryRewriteContext; +import org.elasticsearch.index.query.QueryShardException; import org.elasticsearch.index.query.SearchExecutionContext; import org.elasticsearch.logging.LogManager; import org.elasticsearch.logging.Logger; @@ -26,6 +27,7 @@ import org.elasticsearch.xcontent.XContentParser; import org.elasticsearch.xpack.kql.parser.KqlParser; import org.elasticsearch.xpack.kql.parser.KqlParsingContext; +import org.elasticsearch.xpack.kql.parser.KqlParsingException; import java.io.IOException; import java.time.ZoneId; @@ -37,9 +39,9 @@ public class KqlQueryBuilder extends AbstractQueryBuilder { public static final String NAME = "kql"; public static final ParseField QUERY_FIELD = new ParseField("query"); - private static final ParseField CASE_INSENSITIVE_FIELD = new ParseField("case_insensitive"); - private static final ParseField TIME_ZONE_FIELD = new ParseField("time_zone"); - private static final ParseField DEFAULT_FIELD_FIELD = new ParseField("default_field"); + public static final ParseField CASE_INSENSITIVE_FIELD = new ParseField("case_insensitive"); + public static final ParseField TIME_ZONE_FIELD = new ParseField("time_zone"); + public static final ParseField DEFAULT_FIELD_FIELD = new ParseField("default_field"); private static final Logger log = LogManager.getLogger(KqlQueryBuilder.class); private static final ConstructingObjectParser PARSER = new ConstructingObjectParser<>(NAME, a -> { @@ -151,12 +153,16 @@ protected void doXContent(XContentBuilder builder, Params params) throws IOExcep @Override protected QueryBuilder doIndexMetadataRewrite(QueryRewriteContext context) throws IOException { - KqlParser parser = new KqlParser(); - QueryBuilder rewrittenQuery = parser.parseKqlQuery(query, createKqlParserContext(context)); + try { + KqlParser parser = new KqlParser(); + QueryBuilder rewrittenQuery = parser.parseKqlQuery(query, createKqlParserContext(context)); - log.trace(() -> Strings.format("KQL query %s translated to Query DSL: %s", query, Strings.toString(rewrittenQuery))); + log.trace(() -> Strings.format("KQL query %s translated to Query DSL: %s", query, Strings.toString(rewrittenQuery))); - return rewrittenQuery; + return rewrittenQuery; + } catch (KqlParsingException e) { + throw new QueryShardException(context, "Failed to parse KQL query [{}]", e, query); + } } @Override diff --git a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml index 72c7c51655378..f7dd979540afa 100644 --- a/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml +++ b/x-pack/plugin/src/yamlRestTest/resources/rest-api-spec/test/esql/60_usage.yml @@ -92,7 +92,7 @@ setup: - gt: {esql.functions.to_long: $functions_to_long} - match: {esql.functions.coalesce: $functions_coalesce} # Testing for the entire function set isn't feasbile, so we just check that we return the correct count as an approximation. - - length: {esql.functions: 121} # check the "sister" test below for a likely update to the same esql.functions length check + - length: {esql.functions: 122} # check the "sister" test below for a likely update to the same esql.functions length check --- "Basic ESQL usage output (telemetry) non-snapshot version": From fd6e8857bc9bf56895b3c53996a27c226a3a80fa Mon Sep 17 00:00:00 2001 From: Philippus Baalman Date: Mon, 25 Nov 2024 14:50:09 +0100 Subject: [PATCH 15/34] Mention `bbq_hnsw` for `m` and `ef_construction` options in docs (#117022) --- docs/reference/mapping/types/dense-vector.asciidoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/reference/mapping/types/dense-vector.asciidoc b/docs/reference/mapping/types/dense-vector.asciidoc index 4c16f260c13e7..e6e11d6dd539f 100644 --- a/docs/reference/mapping/types/dense-vector.asciidoc +++ b/docs/reference/mapping/types/dense-vector.asciidoc @@ -338,12 +338,12 @@ by 32x at the cost of accuracy. See < Date: Mon, 25 Nov 2024 14:53:48 +0100 Subject: [PATCH 16/34] =?UTF-8?q?[ML]=20Unmuting=20ForecastIT=20=C2=BB=20t?= =?UTF-8?q?estOverflowToDisk=20for=20Windows=20(#114807)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Running the test on Jenkins caused flakiness in Windows. See #44609. Since we moved to Buildkite I am unmuting this test, assuming that Buildkite is not creating such deep directory structures as Jenkins (see this comment). We will mute this test again, if this assumption turns out to be wrong. Closes #44609. --- .../org/elasticsearch/xpack/ml/integration/ForecastIT.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/x-pack/plugin/ml/qa/native-multi-node-tests/src/javaRestTest/java/org/elasticsearch/xpack/ml/integration/ForecastIT.java b/x-pack/plugin/ml/qa/native-multi-node-tests/src/javaRestTest/java/org/elasticsearch/xpack/ml/integration/ForecastIT.java index 447bca4f4e688..94fbde69e29c7 100644 --- a/x-pack/plugin/ml/qa/native-multi-node-tests/src/javaRestTest/java/org/elasticsearch/xpack/ml/integration/ForecastIT.java +++ b/x-pack/plugin/ml/qa/native-multi-node-tests/src/javaRestTest/java/org/elasticsearch/xpack/ml/integration/ForecastIT.java @@ -6,7 +6,6 @@ */ package org.elasticsearch.xpack.ml.integration; -import org.apache.lucene.util.Constants; import org.elasticsearch.ElasticsearchException; import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.action.support.master.AcknowledgedResponse; @@ -222,8 +221,6 @@ public void testMemoryStatus() { } public void testOverflowToDisk() throws Exception { - assumeFalse("https://github.com/elastic/elasticsearch/issues/44609", Constants.WINDOWS); - Detector.Builder detector = new Detector.Builder("mean", "value"); detector.setByFieldName("clientIP"); From c184b2277769854a102c02d70c7018a50056395c Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Mon, 25 Nov 2024 15:00:44 +0100 Subject: [PATCH 17/34] Stop using _source.mode attribute in builtin templates (#117448) Use index.source.mode index setting in builtin templates instead of the deprecated _source.mode mapping attribute. --- .../metrics-apm@mappings.yaml | 2 -- .../metrics-apm@settings.yaml | 16 +++++++++------- .../apm-data/src/main/resources/resources.yaml | 2 +- .../component-template/profiling-events.json | 8 +++++--- .../profiling-executables.json | 10 ++++++---- .../component-template/profiling-metrics.json | 8 +++++--- .../profiling-stacktraces.json | 8 +++++--- .../index-template/profiling-sq-executables.json | 10 ++++++---- .../index-template/profiling-sq-leafframes.json | 10 ++++++---- .../ProfilingIndexTemplateRegistry.java | 2 +- 10 files changed, 44 insertions(+), 32 deletions(-) diff --git a/x-pack/plugin/apm-data/src/main/resources/component-templates/metrics-apm@mappings.yaml b/x-pack/plugin/apm-data/src/main/resources/component-templates/metrics-apm@mappings.yaml index af28cbb7415a0..660db3a6b0e2e 100644 --- a/x-pack/plugin/apm-data/src/main/resources/component-templates/metrics-apm@mappings.yaml +++ b/x-pack/plugin/apm-data/src/main/resources/component-templates/metrics-apm@mappings.yaml @@ -5,8 +5,6 @@ _meta: managed: true template: mappings: - _source: - mode: synthetic properties: processor.event: type: constant_keyword diff --git a/x-pack/plugin/apm-data/src/main/resources/component-templates/metrics-apm@settings.yaml b/x-pack/plugin/apm-data/src/main/resources/component-templates/metrics-apm@settings.yaml index 819d5d7eafb8e..d8fc13bce79b1 100644 --- a/x-pack/plugin/apm-data/src/main/resources/component-templates/metrics-apm@settings.yaml +++ b/x-pack/plugin/apm-data/src/main/resources/component-templates/metrics-apm@settings.yaml @@ -5,10 +5,12 @@ _meta: managed: true template: settings: - codec: best_compression - mapping: - # apm@settings sets `ignore_malformed: true`, but we need - # to disable this for metrics since they use synthetic source, - # and this combination is incompatible with the - # aggregate_metric_double field type. - ignore_malformed: false + index: + codec: best_compression + mapping: + # apm@settings sets `ignore_malformed: true`, but we need + # to disable this for metrics since they use synthetic source, + # and this combination is incompatible with the + # aggregate_metric_double field type. + ignore_malformed: false + source.mode: synthetic diff --git a/x-pack/plugin/apm-data/src/main/resources/resources.yaml b/x-pack/plugin/apm-data/src/main/resources/resources.yaml index fa209cdec3695..9484f577583eb 100644 --- a/x-pack/plugin/apm-data/src/main/resources/resources.yaml +++ b/x-pack/plugin/apm-data/src/main/resources/resources.yaml @@ -1,7 +1,7 @@ # "version" holds the version of the templates and ingest pipelines installed # by xpack-plugin apm-data. This must be increased whenever an existing template or # pipeline is changed, in order for it to be updated on Elasticsearch upgrade. -version: 11 +version: 12 component-templates: # Data lifecycle. diff --git a/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-events.json b/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-events.json index f90d2202db0d3..c7424571dd678 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-events.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-events.json @@ -15,14 +15,16 @@ "container.name", "process.thread.name" ] + }, + "mapping": { + "source": { + "mode": "synthetic" + } } }, "codec": "best_compression" }, "mappings": { - "_source": { - "mode": "synthetic" - }, "_meta": { "index-template-version": ${xpack.profiling.template.version}, "index-version": ${xpack.profiling.index.events.version}, diff --git a/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-executables.json b/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-executables.json index f1e5e01d50c16..ac72a03202646 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-executables.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-executables.json @@ -5,13 +5,15 @@ "auto_expand_replicas": "0-1", "refresh_interval": "10s", "hidden": true, - "lifecycle.rollover_alias": "profiling-executables" + "lifecycle.rollover_alias": "profiling-executables", + "mapping": { + "source": { + "mode": "synthetic" + } + } } }, "mappings": { - "_source": { - "mode": "synthetic" - }, "_meta": { "index-template-version": ${xpack.profiling.template.version}, "index-version": ${xpack.profiling.index.executables.version}, diff --git a/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-metrics.json b/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-metrics.json index 35f53a36b2d0b..bb893a07c70a1 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-metrics.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-metrics.json @@ -10,14 +10,16 @@ "@timestamp", "host.id" ] + }, + "mapping": { + "source": { + "mode": "synthetic" + } } }, "codec": "best_compression" }, "mappings": { - "_source": { - "mode": "synthetic" - }, "_meta": { "index-template-version": ${xpack.profiling.template.version}, "index-version": ${xpack.profiling.index.metrics.version}, diff --git a/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-stacktraces.json b/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-stacktraces.json index 6c96fb21673ae..1170e3a32d8e2 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-stacktraces.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/profiling/component-template/profiling-stacktraces.json @@ -11,13 +11,15 @@ "field": [ "Stacktrace.frame.ids" ] + }, + "mapping": { + "source": { + "mode": "synthetic" + } } } }, "mappings": { - "_source": { - "mode": "synthetic" - }, "_meta": { "index-template-version": ${xpack.profiling.template.version}, "index-version": ${xpack.profiling.index.stacktraces.version}, diff --git a/x-pack/plugin/core/template-resources/src/main/resources/profiling/index-template/profiling-sq-executables.json b/x-pack/plugin/core/template-resources/src/main/resources/profiling/index-template/profiling-sq-executables.json index 71c4d15989b7a..d5d24a22fc58e 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/profiling/index-template/profiling-sq-executables.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/profiling/index-template/profiling-sq-executables.json @@ -7,13 +7,15 @@ "index": { "auto_expand_replicas": "0-1", "refresh_interval": "10s", - "hidden": true + "hidden": true, + "mapping": { + "source": { + "mode": "synthetic" + } + } } }, "mappings": { - "_source": { - "mode": "synthetic" - }, "_meta": { "index-template-version": ${xpack.profiling.template.version}, "index-version": ${xpack.profiling.index.sq.executables.version}, diff --git a/x-pack/plugin/core/template-resources/src/main/resources/profiling/index-template/profiling-sq-leafframes.json b/x-pack/plugin/core/template-resources/src/main/resources/profiling/index-template/profiling-sq-leafframes.json index 20849bfe8f27d..b56b4b2874743 100644 --- a/x-pack/plugin/core/template-resources/src/main/resources/profiling/index-template/profiling-sq-leafframes.json +++ b/x-pack/plugin/core/template-resources/src/main/resources/profiling/index-template/profiling-sq-leafframes.json @@ -7,13 +7,15 @@ "index": { "auto_expand_replicas": "0-1", "refresh_interval": "10s", - "hidden": true + "hidden": true, + "mapping": { + "source": { + "mode": "synthetic" + } + } } }, "mappings": { - "_source": { - "mode": "synthetic" - }, "_meta": { "index-template-version": ${xpack.profiling.template.version}, "index-version": ${xpack.profiling.index.sq.leafframes.version}, diff --git a/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/persistence/ProfilingIndexTemplateRegistry.java b/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/persistence/ProfilingIndexTemplateRegistry.java index 7d8a474453c4c..71e8dcbff4ee6 100644 --- a/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/persistence/ProfilingIndexTemplateRegistry.java +++ b/x-pack/plugin/profiling/src/main/java/org/elasticsearch/xpack/profiling/persistence/ProfilingIndexTemplateRegistry.java @@ -54,7 +54,7 @@ public class ProfilingIndexTemplateRegistry extends IndexTemplateRegistry { // version 11: Added 'profiling.agent.protocol' keyword mapping to profiling-hosts // version 12: Added 'profiling.agent.env_https_proxy' keyword mapping to profiling-hosts // version 13: Added 'container.id' keyword mapping to profiling-events - public static final int INDEX_TEMPLATE_VERSION = 13; + public static final int INDEX_TEMPLATE_VERSION = 14; // history for individual indices / index templates. Only bump these for breaking changes that require to create a new index public static final int PROFILING_EVENTS_VERSION = 5; From fa9f2bff0edafae15816f9a77df979e3a38f4e9c Mon Sep 17 00:00:00 2001 From: florent-leborgne Date: Mon, 25 Nov 2024 15:13:23 +0100 Subject: [PATCH 18/34] Docs for starred esql queries in Kibana (#117468) --- docs/reference/esql/esql-kibana.asciidoc | 17 ++++++++++++++++- .../esql/esql-discover-query-history.png | Bin 290854 -> 217954 bytes .../esql/esql-discover-query-starred.png | Bin 0 -> 209828 bytes 3 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 docs/reference/images/esql/esql-discover-query-starred.png diff --git a/docs/reference/esql/esql-kibana.asciidoc b/docs/reference/esql/esql-kibana.asciidoc index 85969e19957af..87dd4d87fa8e3 100644 --- a/docs/reference/esql/esql-kibana.asciidoc +++ b/docs/reference/esql/esql-kibana.asciidoc @@ -106,12 +106,27 @@ detailed warning, expand the query bar, and click *warnings*. ==== Query history You can reuse your recent {esql} queries in the query bar. -In the query bar click *Show recent queries*. +In the query bar, click *Show recent queries*. You can then scroll through your recent queries: image::images/esql/esql-discover-query-history.png[align="center",size="50%"] +[discrete] +[[esql-kibana-starred-queries]] +==== Starred queries + +From the query history, you can mark some queries as favorite to find and access them faster later. + +In the query bar, click *Show recent queries*. + +From the **Recent** tab, you can star any queries you want. + +In the **Starred** tab, find all the queries you have previously starred. + +image::images/esql/esql-discover-query-starred.png[align="center",size="50%"] + + [discrete] [[esql-kibana-results-table]] === The results table diff --git a/docs/reference/images/esql/esql-discover-query-history.png b/docs/reference/images/esql/esql-discover-query-history.png index ff1d2ffa8b280eff5ba369c10e3e3db1fab4431f..eb064684af700cc791312dfe8aba2ee1122e4a53 100644 GIT binary patch literal 217954 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

-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 z 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

teHuRh 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

QIo;l*ZJvlj>rhM)zybs5z!JZr&(vP2yH!YK6J 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 literal 0 HcmV?d00001 From 9981a1d905590bb300a0f3c547d8c9cd1e251ddd Mon Sep 17 00:00:00 2001 From: Dan Rubinstein Date: Mon, 25 Nov 2024 10:27:31 -0500 Subject: [PATCH 19/34] Adding endpoint creation validation for all task types to remaining services (#115020) * Adding endpoint creation validation for all task types to remaining services * Update Cohere IT tests for rerank validation * Adding missing import * Update docs/changelog/115020.yaml * Fixing GoogleVertex tests after merge from upstream --------- Co-authored-by: Elastic Machine --- docs/changelog/115020.yaml | 5 ++ .../qa/mixed/CohereServiceMixedIT.java | 1 + .../application/CohereServiceUpgradeIT.java | 2 + .../AlibabaCloudSearchService.java | 76 ++++++------------- .../amazonbedrock/AmazonBedrockService.java | 64 ++++++---------- .../services/anthropic/AnthropicService.java | 7 ++ .../azureopenai/AzureOpenAiService.java | 62 ++++++--------- .../services/cohere/CohereService.java | 48 ++++++------ .../googlevertexai/GoogleVertexAiService.java | 57 +++++--------- .../ibmwatsonx/IbmWatsonxService.java | 46 +++++------ .../AlibabaCloudSearchServiceTests.java | 40 ++++++++++ .../AmazonBedrockServiceTests.java | 74 ++++++++++++++++++ .../azureopenai/AzureOpenAiServiceTests.java | 47 ++++++++++++ .../services/cohere/CohereServiceTests.java | 44 +++++++++++ .../GoogleVertexAiServiceTests.java | 34 +++++++++ .../GoogleVertexAiEmbeddingsModelTests.java | 33 +++++++- .../ibmwatsonx/IbmWatsonxServiceTests.java | 51 +++++++++++++ 17 files changed, 473 insertions(+), 218 deletions(-) create mode 100644 docs/changelog/115020.yaml diff --git a/docs/changelog/115020.yaml b/docs/changelog/115020.yaml new file mode 100644 index 0000000000000..2b0aefafea507 --- /dev/null +++ b/docs/changelog/115020.yaml @@ -0,0 +1,5 @@ +pr: 115020 +summary: Adding endpoint creation validation for all task types to remaining services +area: Machine Learning +type: enhancement +issues: [] diff --git a/x-pack/plugin/inference/qa/mixed-cluster/src/javaRestTest/java/org/elasticsearch/xpack/inference/qa/mixed/CohereServiceMixedIT.java b/x-pack/plugin/inference/qa/mixed-cluster/src/javaRestTest/java/org/elasticsearch/xpack/inference/qa/mixed/CohereServiceMixedIT.java index 8cb37ad645358..c16271ed44083 100644 --- a/x-pack/plugin/inference/qa/mixed-cluster/src/javaRestTest/java/org/elasticsearch/xpack/inference/qa/mixed/CohereServiceMixedIT.java +++ b/x-pack/plugin/inference/qa/mixed-cluster/src/javaRestTest/java/org/elasticsearch/xpack/inference/qa/mixed/CohereServiceMixedIT.java @@ -135,6 +135,7 @@ public void testRerank() throws IOException { final String inferenceId = "mixed-cluster-rerank"; + cohereRerankServer.enqueue(new MockResponse().setResponseCode(200).setBody(rerankResponse())); put(inferenceId, rerankConfig(getUrl(cohereRerankServer)), TaskType.RERANK); assertRerank(inferenceId); diff --git a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/CohereServiceUpgradeIT.java b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/CohereServiceUpgradeIT.java index 32969ffd1d112..0acbc148515bd 100644 --- a/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/CohereServiceUpgradeIT.java +++ b/x-pack/plugin/inference/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/xpack/application/CohereServiceUpgradeIT.java @@ -201,6 +201,7 @@ public void testRerank() throws IOException { var testTaskType = TaskType.RERANK; if (isOldCluster()) { + cohereRerankServer.enqueue(new MockResponse().setResponseCode(200).setBody(rerankResponse())); put(oldClusterId, rerankConfig(getUrl(cohereRerankServer)), testTaskType); var configs = (List>) get(testTaskType, oldClusterId).get(old_cluster_endpoint_identifier); assertThat(configs, hasSize(1)); @@ -229,6 +230,7 @@ public void testRerank() throws IOException { assertRerank(oldClusterId); // New endpoint + cohereRerankServer.enqueue(new MockResponse().setResponseCode(200).setBody(rerankResponse())); put(upgradedClusterId, rerankConfig(getUrl(cohereRerankServer)), testTaskType); configs = (List>) get(upgradedClusterId).get("endpoints"); assertThat(configs, hasSize(1)); diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/alibabacloudsearch/AlibabaCloudSearchService.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/alibabacloudsearch/AlibabaCloudSearchService.java index c84b4314b9d1a..6d77663f49ece 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/alibabacloudsearch/AlibabaCloudSearchService.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/alibabacloudsearch/AlibabaCloudSearchService.java @@ -18,7 +18,6 @@ import org.elasticsearch.inference.ChunkingOptions; import org.elasticsearch.inference.ChunkingSettings; import org.elasticsearch.inference.EmptySettingsConfiguration; -import org.elasticsearch.inference.InferenceService; import org.elasticsearch.inference.InferenceServiceConfiguration; import org.elasticsearch.inference.InferenceServiceResults; import org.elasticsearch.inference.InputType; @@ -51,6 +50,7 @@ import org.elasticsearch.xpack.inference.services.alibabacloudsearch.sparse.AlibabaCloudSearchSparseModel; import org.elasticsearch.xpack.inference.services.settings.DefaultSecretSettings; import org.elasticsearch.xpack.inference.services.settings.RateLimitSettings; +import org.elasticsearch.xpack.inference.services.validation.ModelValidatorBuilder; import java.util.EnumSet; import java.util.HashMap; @@ -60,7 +60,6 @@ import static org.elasticsearch.inference.TaskType.SPARSE_EMBEDDING; import static org.elasticsearch.inference.TaskType.TEXT_EMBEDDING; -import static org.elasticsearch.xpack.core.inference.action.InferenceAction.Request.DEFAULT_TIMEOUT; import static org.elasticsearch.xpack.inference.services.ServiceUtils.createInvalidModelException; import static org.elasticsearch.xpack.inference.services.ServiceUtils.parsePersistedConfigErrorMsg; import static org.elasticsearch.xpack.inference.services.ServiceUtils.removeFromMap; @@ -332,68 +331,39 @@ private EmbeddingRequestChunker.EmbeddingType getEmbeddingTypeFromTaskType(TaskT */ @Override public void checkModelConfig(Model model, ActionListener listener) { + // TODO: Remove this function once all services have been updated to use the new model validators + ModelValidatorBuilder.buildModelValidator(model.getTaskType()).validate(this, model, listener); + } + + @Override + public Model updateModelWithEmbeddingDetails(Model model, int embeddingSize) { if (model instanceof AlibabaCloudSearchEmbeddingsModel embeddingsModel) { - ServiceUtils.getEmbeddingSize( - model, - this, - listener.delegateFailureAndWrap((l, size) -> l.onResponse(updateModelWithEmbeddingDetails(embeddingsModel, size))) + var serviceSettings = embeddingsModel.getServiceSettings(); + + var updatedServiceSettings = new AlibabaCloudSearchEmbeddingsServiceSettings( + new AlibabaCloudSearchServiceSettings( + serviceSettings.getCommonSettings().modelId(), + serviceSettings.getCommonSettings().getHost(), + serviceSettings.getCommonSettings().getWorkspaceName(), + serviceSettings.getCommonSettings().getHttpSchema(), + serviceSettings.getCommonSettings().rateLimitSettings() + ), + SimilarityMeasure.DOT_PRODUCT, + embeddingSize, + serviceSettings.getMaxInputTokens() ); + + return new AlibabaCloudSearchEmbeddingsModel(embeddingsModel, updatedServiceSettings); } else { - checkAlibabaCloudSearchServiceConfig(model, this, listener); + throw ServiceUtils.invalidModelTypeForUpdateModelWithEmbeddingDetails(model.getClass()); } } - private AlibabaCloudSearchEmbeddingsModel updateModelWithEmbeddingDetails(AlibabaCloudSearchEmbeddingsModel model, int embeddingSize) { - AlibabaCloudSearchEmbeddingsServiceSettings serviceSettings = new AlibabaCloudSearchEmbeddingsServiceSettings( - new AlibabaCloudSearchServiceSettings( - model.getServiceSettings().getCommonSettings().modelId(), - model.getServiceSettings().getCommonSettings().getHost(), - model.getServiceSettings().getCommonSettings().getWorkspaceName(), - model.getServiceSettings().getCommonSettings().getHttpSchema(), - model.getServiceSettings().getCommonSettings().rateLimitSettings() - ), - SimilarityMeasure.DOT_PRODUCT, - embeddingSize, - model.getServiceSettings().getMaxInputTokens() - ); - - return new AlibabaCloudSearchEmbeddingsModel(model, serviceSettings); - } - @Override public TransportVersion getMinimalSupportedVersion() { return TransportVersions.ML_INFERENCE_ALIBABACLOUD_SEARCH_ADDED; } - /** - * For other models except of text embedding - * check the model's service settings and task settings - * - * @param model The new model - * @param service The inferenceService - * @param listener The listener - */ - private void checkAlibabaCloudSearchServiceConfig(Model model, InferenceService service, ActionListener listener) { - String input = ALIBABA_CLOUD_SEARCH_SERVICE_CONFIG_INPUT; - String query = model.getTaskType().equals(TaskType.RERANK) ? ALIBABA_CLOUD_SEARCH_SERVICE_CONFIG_QUERY : null; - - service.infer( - model, - query, - List.of(input), - false, - Map.of(), - InputType.INGEST, - DEFAULT_TIMEOUT, - listener.delegateFailureAndWrap((delegate, r) -> { - listener.onResponse(model); - }) - ); - } - - private static final String ALIBABA_CLOUD_SEARCH_SERVICE_CONFIG_INPUT = "input"; - private static final String ALIBABA_CLOUD_SEARCH_SERVICE_CONFIG_QUERY = "query"; - public static class Configuration { public static InferenceServiceConfiguration get() { return configuration.getOrCompute(); diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/amazonbedrock/AmazonBedrockService.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/amazonbedrock/AmazonBedrockService.java index f9822c7ab4af9..a69b9d2c70405 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/amazonbedrock/AmazonBedrockService.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/amazonbedrock/AmazonBedrockService.java @@ -49,6 +49,7 @@ import org.elasticsearch.xpack.inference.services.amazonbedrock.embeddings.AmazonBedrockEmbeddingsModel; import org.elasticsearch.xpack.inference.services.amazonbedrock.embeddings.AmazonBedrockEmbeddingsServiceSettings; import org.elasticsearch.xpack.inference.services.settings.RateLimitSettings; +import org.elasticsearch.xpack.inference.services.validation.ModelValidatorBuilder; import java.io.IOException; import java.util.EnumSet; @@ -303,49 +304,34 @@ public Set supportedStreamingTasks() { */ @Override public void checkModelConfig(Model model, ActionListener listener) { - if (model instanceof AmazonBedrockEmbeddingsModel embeddingsModel) { - ServiceUtils.getEmbeddingSize( - model, - this, - listener.delegateFailureAndWrap((l, size) -> l.onResponse(updateModelWithEmbeddingDetails(embeddingsModel, size))) - ); - } else { - listener.onResponse(model); - } + // TODO: Remove this function once all services have been updated to use the new model validators + ModelValidatorBuilder.buildModelValidator(model.getTaskType()).validate(this, model, listener); } - private AmazonBedrockEmbeddingsModel updateModelWithEmbeddingDetails(AmazonBedrockEmbeddingsModel model, int embeddingSize) { - AmazonBedrockEmbeddingsServiceSettings serviceSettings = model.getServiceSettings(); - if (serviceSettings.dimensionsSetByUser() - && serviceSettings.dimensions() != null - && serviceSettings.dimensions() != embeddingSize) { - throw new ElasticsearchStatusException( - Strings.format( - "The retrieved embeddings size [%s] does not match the size specified in the settings [%s]. " - + "Please recreate the [%s] configuration with the correct dimensions", - embeddingSize, - serviceSettings.dimensions(), - model.getConfigurations().getInferenceEntityId() - ), - RestStatus.BAD_REQUEST + @Override + public Model updateModelWithEmbeddingDetails(Model model, int embeddingSize) { + if (model instanceof AmazonBedrockEmbeddingsModel embeddingsModel) { + var serviceSettings = embeddingsModel.getServiceSettings(); + var similarityFromModel = serviceSettings.similarity(); + var similarityToUse = similarityFromModel == null + ? getProviderDefaultSimilarityMeasure(embeddingsModel.provider()) + : similarityFromModel; + + var updatedServiceSettings = new AmazonBedrockEmbeddingsServiceSettings( + serviceSettings.region(), + serviceSettings.modelId(), + serviceSettings.provider(), + embeddingSize, + serviceSettings.dimensionsSetByUser(), + serviceSettings.maxInputTokens(), + similarityToUse, + serviceSettings.rateLimitSettings() ); - } - - var similarityFromModel = serviceSettings.similarity(); - var similarityToUse = similarityFromModel == null ? getProviderDefaultSimilarityMeasure(model.provider()) : similarityFromModel; - - AmazonBedrockEmbeddingsServiceSettings settingsToUse = new AmazonBedrockEmbeddingsServiceSettings( - serviceSettings.region(), - serviceSettings.modelId(), - serviceSettings.provider(), - embeddingSize, - serviceSettings.dimensionsSetByUser(), - serviceSettings.maxInputTokens(), - similarityToUse, - serviceSettings.rateLimitSettings() - ); - return new AmazonBedrockEmbeddingsModel(model, settingsToUse); + return new AmazonBedrockEmbeddingsModel(embeddingsModel, updatedServiceSettings); + } else { + throw ServiceUtils.invalidModelTypeForUpdateModelWithEmbeddingDetails(model.getClass()); + } } private static void checkProviderForTask(TaskType taskType, AmazonBedrockProvider provider) { diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/anthropic/AnthropicService.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/anthropic/AnthropicService.java index 556b34b945c14..eba7353f2b12e 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/anthropic/AnthropicService.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/anthropic/AnthropicService.java @@ -39,6 +39,7 @@ import org.elasticsearch.xpack.inference.services.anthropic.completion.AnthropicChatCompletionModel; import org.elasticsearch.xpack.inference.services.settings.DefaultSecretSettings; import org.elasticsearch.xpack.inference.services.settings.RateLimitSettings; +import org.elasticsearch.xpack.inference.services.validation.ModelValidatorBuilder; import java.util.EnumSet; import java.util.HashMap; @@ -176,6 +177,12 @@ public AnthropicModel parsePersistedConfig(String inferenceEntityId, TaskType ta ); } + @Override + public void checkModelConfig(Model model, ActionListener listener) { + // TODO: Remove this function once all services have been updated to use the new model validators + ModelValidatorBuilder.buildModelValidator(model.getTaskType()).validate(this, model, listener); + } + @Override public InferenceServiceConfiguration getConfiguration() { return Configuration.get(); diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiService.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiService.java index 6d36e5f6c8fe7..2f3a935cdf010 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiService.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiService.java @@ -11,7 +11,6 @@ import org.elasticsearch.TransportVersion; import org.elasticsearch.TransportVersions; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.Strings; import org.elasticsearch.common.util.LazyInitializable; import org.elasticsearch.core.Nullable; import org.elasticsearch.core.TimeValue; @@ -46,6 +45,7 @@ import org.elasticsearch.xpack.inference.services.azureopenai.embeddings.AzureOpenAiEmbeddingsModel; import org.elasticsearch.xpack.inference.services.azureopenai.embeddings.AzureOpenAiEmbeddingsServiceSettings; import org.elasticsearch.xpack.inference.services.settings.RateLimitSettings; +import org.elasticsearch.xpack.inference.services.validation.ModelValidatorBuilder; import java.util.EnumSet; import java.util.HashMap; @@ -294,48 +294,32 @@ protected void doChunkedInfer( */ @Override public void checkModelConfig(Model model, ActionListener listener) { - if (model instanceof AzureOpenAiEmbeddingsModel embeddingsModel) { - ServiceUtils.getEmbeddingSize( - model, - this, - listener.delegateFailureAndWrap((l, size) -> l.onResponse(updateModelWithEmbeddingDetails(embeddingsModel, size))) - ); - } else { - listener.onResponse(model); - } + // TODO: Remove this function once all services have been updated to use the new model validators + ModelValidatorBuilder.buildModelValidator(model.getTaskType()).validate(this, model, listener); } - private AzureOpenAiEmbeddingsModel updateModelWithEmbeddingDetails(AzureOpenAiEmbeddingsModel model, int embeddingSize) { - if (model.getServiceSettings().dimensionsSetByUser() - && model.getServiceSettings().dimensions() != null - && model.getServiceSettings().dimensions() != embeddingSize) { - throw new ElasticsearchStatusException( - Strings.format( - "The retrieved embeddings size [%s] does not match the size specified in the settings [%s]. " - + "Please recreate the [%s] configuration with the correct dimensions", - embeddingSize, - model.getServiceSettings().dimensions(), - model.getConfigurations().getInferenceEntityId() - ), - RestStatus.BAD_REQUEST + @Override + public Model updateModelWithEmbeddingDetails(Model model, int embeddingSize) { + if (model instanceof AzureOpenAiEmbeddingsModel embeddingsModel) { + var serviceSettings = embeddingsModel.getServiceSettings(); + var similarityFromModel = serviceSettings.similarity(); + var similarityToUse = similarityFromModel == null ? SimilarityMeasure.DOT_PRODUCT : similarityFromModel; + + var updatedServiceSettings = new AzureOpenAiEmbeddingsServiceSettings( + serviceSettings.resourceName(), + serviceSettings.deploymentId(), + serviceSettings.apiVersion(), + embeddingSize, + serviceSettings.dimensionsSetByUser(), + serviceSettings.maxInputTokens(), + similarityToUse, + serviceSettings.rateLimitSettings() ); - } - - var similarityFromModel = model.getServiceSettings().similarity(); - var similarityToUse = similarityFromModel == null ? SimilarityMeasure.DOT_PRODUCT : similarityFromModel; - - AzureOpenAiEmbeddingsServiceSettings serviceSettings = new AzureOpenAiEmbeddingsServiceSettings( - model.getServiceSettings().resourceName(), - model.getServiceSettings().deploymentId(), - model.getServiceSettings().apiVersion(), - embeddingSize, - model.getServiceSettings().dimensionsSetByUser(), - model.getServiceSettings().maxInputTokens(), - similarityToUse, - model.getServiceSettings().rateLimitSettings() - ); - return new AzureOpenAiEmbeddingsModel(model, serviceSettings); + return new AzureOpenAiEmbeddingsModel(embeddingsModel, updatedServiceSettings); + } else { + throw ServiceUtils.invalidModelTypeForUpdateModelWithEmbeddingDetails(model.getClass()); + } } @Override diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/cohere/CohereService.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/cohere/CohereService.java index de1d055e160da..cc67470686a02 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/cohere/CohereService.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/cohere/CohereService.java @@ -45,6 +45,7 @@ import org.elasticsearch.xpack.inference.services.cohere.rerank.CohereRerankModel; import org.elasticsearch.xpack.inference.services.settings.DefaultSecretSettings; import org.elasticsearch.xpack.inference.services.settings.RateLimitSettings; +import org.elasticsearch.xpack.inference.services.validation.ModelValidatorBuilder; import java.util.EnumSet; import java.util.HashMap; @@ -293,36 +294,35 @@ protected void doChunkedInfer( */ @Override public void checkModelConfig(Model model, ActionListener listener) { + // TODO: Remove this function once all services have been updated to use the new model validators + ModelValidatorBuilder.buildModelValidator(model.getTaskType()).validate(this, model, listener); + } + + @Override + public Model updateModelWithEmbeddingDetails(Model model, int embeddingSize) { if (model instanceof CohereEmbeddingsModel embeddingsModel) { - ServiceUtils.getEmbeddingSize( - model, - this, - listener.delegateFailureAndWrap((l, size) -> l.onResponse(updateModelWithEmbeddingDetails(embeddingsModel, size))) + var serviceSettings = embeddingsModel.getServiceSettings(); + var similarityFromModel = serviceSettings.similarity(); + var similarityToUse = similarityFromModel == null ? defaultSimilarity() : similarityFromModel; + + var updatedServiceSettings = new CohereEmbeddingsServiceSettings( + new CohereServiceSettings( + serviceSettings.getCommonSettings().uri(), + similarityToUse, + embeddingSize, + serviceSettings.getCommonSettings().maxInputTokens(), + serviceSettings.getCommonSettings().modelId(), + serviceSettings.getCommonSettings().rateLimitSettings() + ), + serviceSettings.getEmbeddingType() ); + + return new CohereEmbeddingsModel(embeddingsModel, updatedServiceSettings); } else { - listener.onResponse(model); + throw ServiceUtils.invalidModelTypeForUpdateModelWithEmbeddingDetails(model.getClass()); } } - private CohereEmbeddingsModel updateModelWithEmbeddingDetails(CohereEmbeddingsModel model, int embeddingSize) { - var userDefinedSimilarity = model.getServiceSettings().similarity(); - var similarityToUse = userDefinedSimilarity == null ? defaultSimilarity() : userDefinedSimilarity; - - CohereEmbeddingsServiceSettings serviceSettings = new CohereEmbeddingsServiceSettings( - new CohereServiceSettings( - model.getServiceSettings().getCommonSettings().uri(), - similarityToUse, - embeddingSize, - model.getServiceSettings().getCommonSettings().maxInputTokens(), - model.getServiceSettings().getCommonSettings().modelId(), - model.getServiceSettings().getCommonSettings().rateLimitSettings() - ), - model.getServiceSettings().getEmbeddingType() - ); - - return new CohereEmbeddingsModel(model, serviceSettings); - } - /** * Return the default similarity measure for the embedding type. * Cohere embeddings are normalized to unit vectors therefor Dot diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/googlevertexai/GoogleVertexAiService.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/googlevertexai/GoogleVertexAiService.java index a05b1a937d376..204593464a4ad 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/googlevertexai/GoogleVertexAiService.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/googlevertexai/GoogleVertexAiService.java @@ -11,7 +11,6 @@ import org.elasticsearch.TransportVersion; import org.elasticsearch.TransportVersions; import org.elasticsearch.action.ActionListener; -import org.elasticsearch.common.Strings; import org.elasticsearch.common.util.LazyInitializable; import org.elasticsearch.core.Nullable; import org.elasticsearch.core.TimeValue; @@ -45,6 +44,7 @@ import org.elasticsearch.xpack.inference.services.googlevertexai.embeddings.GoogleVertexAiEmbeddingsServiceSettings; import org.elasticsearch.xpack.inference.services.googlevertexai.rerank.GoogleVertexAiRerankModel; import org.elasticsearch.xpack.inference.services.settings.RateLimitSettings; +import org.elasticsearch.xpack.inference.services.validation.ModelValidatorBuilder; import java.util.EnumSet; import java.util.HashMap; @@ -181,15 +181,8 @@ public TransportVersion getMinimalSupportedVersion() { @Override public void checkModelConfig(Model model, ActionListener listener) { - if (model instanceof GoogleVertexAiEmbeddingsModel embeddingsModel) { - ServiceUtils.getEmbeddingSize( - model, - this, - listener.delegateFailureAndWrap((l, size) -> l.onResponse(updateModelWithEmbeddingDetails(embeddingsModel, size))) - ); - } else { - listener.onResponse(model); - } + // TODO: Remove this function once all services have been updated to use the new model validators + ModelValidatorBuilder.buildModelValidator(model.getTaskType()).validate(this, model, listener); } @Override @@ -240,34 +233,26 @@ protected void doChunkedInfer( } } - private GoogleVertexAiEmbeddingsModel updateModelWithEmbeddingDetails(GoogleVertexAiEmbeddingsModel model, int embeddingSize) { - if (model.getServiceSettings().dimensionsSetByUser() - && model.getServiceSettings().dimensions() != null - && model.getServiceSettings().dimensions() != embeddingSize) { - throw new ElasticsearchStatusException( - Strings.format( - "The retrieved embeddings size [%s] does not match the size specified in the settings [%s]. " - + "Please recreate the [%s] configuration with the correct dimensions", - embeddingSize, - model.getServiceSettings().dimensions(), - model.getConfigurations().getInferenceEntityId() - ), - RestStatus.BAD_REQUEST + @Override + public Model updateModelWithEmbeddingDetails(Model model, int embeddingSize) { + if (model instanceof GoogleVertexAiEmbeddingsModel embeddingsModel) { + var serviceSettings = embeddingsModel.getServiceSettings(); + + var updatedServiceSettings = new GoogleVertexAiEmbeddingsServiceSettings( + serviceSettings.location(), + serviceSettings.projectId(), + serviceSettings.modelId(), + serviceSettings.dimensionsSetByUser(), + serviceSettings.maxInputTokens(), + embeddingSize, + serviceSettings.similarity(), + serviceSettings.rateLimitSettings() ); - } - - GoogleVertexAiEmbeddingsServiceSettings serviceSettings = new GoogleVertexAiEmbeddingsServiceSettings( - model.getServiceSettings().location(), - model.getServiceSettings().projectId(), - model.getServiceSettings().modelId(), - model.getServiceSettings().dimensionsSetByUser(), - model.getServiceSettings().maxInputTokens(), - embeddingSize, - model.getServiceSettings().similarity(), - model.getServiceSettings().rateLimitSettings() - ); - return new GoogleVertexAiEmbeddingsModel(model, serviceSettings); + return new GoogleVertexAiEmbeddingsModel(embeddingsModel, updatedServiceSettings); + } else { + throw ServiceUtils.invalidModelTypeForUpdateModelWithEmbeddingDetails(model.getClass()); + } } private static GoogleVertexAiModel createModelFromPersistent( diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/ibmwatsonx/IbmWatsonxService.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/ibmwatsonx/IbmWatsonxService.java index f4f4605c667c3..592900d117b39 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/ibmwatsonx/IbmWatsonxService.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/ibmwatsonx/IbmWatsonxService.java @@ -44,6 +44,7 @@ import org.elasticsearch.xpack.inference.services.ServiceUtils; import org.elasticsearch.xpack.inference.services.ibmwatsonx.embeddings.IbmWatsonxEmbeddingsModel; import org.elasticsearch.xpack.inference.services.ibmwatsonx.embeddings.IbmWatsonxEmbeddingsServiceSettings; +import org.elasticsearch.xpack.inference.services.validation.ModelValidatorBuilder; import java.util.EnumSet; import java.util.HashMap; @@ -228,35 +229,34 @@ public TransportVersion getMinimalSupportedVersion() { @Override public void checkModelConfig(Model model, ActionListener listener) { + // TODO: Remove this function once all services have been updated to use the new model validators + ModelValidatorBuilder.buildModelValidator(model.getTaskType()).validate(this, model, listener); + } + + @Override + public Model updateModelWithEmbeddingDetails(Model model, int embeddingSize) { if (model instanceof IbmWatsonxEmbeddingsModel embeddingsModel) { - ServiceUtils.getEmbeddingSize( - model, - this, - listener.delegateFailureAndWrap((l, size) -> l.onResponse(updateModelWithEmbeddingDetails(embeddingsModel, size))) + var serviceSettings = embeddingsModel.getServiceSettings(); + var similarityFromModel = serviceSettings.similarity(); + var similarityToUse = similarityFromModel == null ? SimilarityMeasure.DOT_PRODUCT : similarityFromModel; + + var updatedServiceSettings = new IbmWatsonxEmbeddingsServiceSettings( + serviceSettings.modelId(), + serviceSettings.projectId(), + serviceSettings.url(), + serviceSettings.apiVersion(), + serviceSettings.maxInputTokens(), + embeddingSize, + similarityToUse, + serviceSettings.rateLimitSettings() ); + + return new IbmWatsonxEmbeddingsModel(embeddingsModel, updatedServiceSettings); } else { - listener.onResponse(model); + throw ServiceUtils.invalidModelTypeForUpdateModelWithEmbeddingDetails(model.getClass()); } } - private IbmWatsonxEmbeddingsModel updateModelWithEmbeddingDetails(IbmWatsonxEmbeddingsModel model, int embeddingSize) { - var similarityFromModel = model.getServiceSettings().similarity(); - var similarityToUse = similarityFromModel == null ? SimilarityMeasure.DOT_PRODUCT : similarityFromModel; - - IbmWatsonxEmbeddingsServiceSettings serviceSettings = new IbmWatsonxEmbeddingsServiceSettings( - model.getServiceSettings().modelId(), - model.getServiceSettings().projectId(), - model.getServiceSettings().url(), - model.getServiceSettings().apiVersion(), - model.getServiceSettings().maxInputTokens(), - embeddingSize, - similarityToUse, - model.getServiceSettings().rateLimitSettings() - ); - - return new IbmWatsonxEmbeddingsModel(model, serviceSettings); - } - @Override protected void doInfer( Model model, diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/alibabacloudsearch/AlibabaCloudSearchServiceTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/alibabacloudsearch/AlibabaCloudSearchServiceTests.java index aac111c22558e..b6d29ccab9a49 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/alibabacloudsearch/AlibabaCloudSearchServiceTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/alibabacloudsearch/AlibabaCloudSearchServiceTests.java @@ -7,6 +7,7 @@ package org.elasticsearch.xpack.inference.services.alibabacloudsearch; +import org.elasticsearch.ElasticsearchStatusException; import org.elasticsearch.action.ActionListener; import org.elasticsearch.action.support.PlainActionFuture; import org.elasticsearch.common.bytes.BytesArray; @@ -22,6 +23,7 @@ import org.elasticsearch.inference.InputType; import org.elasticsearch.inference.Model; import org.elasticsearch.inference.ModelConfigurations; +import org.elasticsearch.inference.SimilarityMeasure; import org.elasticsearch.inference.TaskType; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.threadpool.ThreadPool; @@ -50,6 +52,7 @@ import org.elasticsearch.xpack.inference.services.alibabacloudsearch.embeddings.AlibabaCloudSearchEmbeddingsServiceSettingsTests; import org.elasticsearch.xpack.inference.services.alibabacloudsearch.embeddings.AlibabaCloudSearchEmbeddingsTaskSettingsTests; import org.elasticsearch.xpack.inference.services.alibabacloudsearch.sparse.AlibabaCloudSearchSparseModel; +import org.elasticsearch.xpack.inference.services.openai.completion.OpenAiChatCompletionModelTests; import org.hamcrest.MatcherAssert; import org.junit.After; import org.junit.Before; @@ -325,6 +328,43 @@ public void doInfer( } } + public void testUpdateModelWithEmbeddingDetails_InvalidModelProvided() throws IOException { + var senderFactory = HttpRequestSenderTests.createSenderFactory(threadPool, clientManager); + + try (var service = new AlibabaCloudSearchService(senderFactory, createWithEmptySettings(threadPool))) { + var model = OpenAiChatCompletionModelTests.createChatCompletionModel( + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10) + ); + assertThrows( + ElasticsearchStatusException.class, + () -> { service.updateModelWithEmbeddingDetails(model, randomNonNegativeInt()); } + ); + } + } + + public void testUpdateModelWithEmbeddingDetails_UpdatesEmbeddingSizeAndSimilarity() throws IOException { + var senderFactory = HttpRequestSenderTests.createSenderFactory(threadPool, clientManager); + try (var service = new AlibabaCloudSearchService(senderFactory, createWithEmptySettings(threadPool))) { + var embeddingSize = randomNonNegativeInt(); + var model = AlibabaCloudSearchEmbeddingsModelTests.createModel( + randomAlphaOfLength(10), + randomFrom(TaskType.values()), + AlibabaCloudSearchEmbeddingsServiceSettingsTests.createRandom(), + AlibabaCloudSearchEmbeddingsTaskSettingsTests.createRandom(), + null + ); + + Model updatedModel = service.updateModelWithEmbeddingDetails(model, embeddingSize); + + assertEquals(SimilarityMeasure.DOT_PRODUCT, updatedModel.getServiceSettings().similarity()); + assertEquals(embeddingSize, updatedModel.getServiceSettings().dimensions().intValue()); + } + } + public void testChunkedInfer_TextEmbeddingChunkingSettingsSet() throws IOException { testChunkedInfer(TaskType.TEXT_EMBEDDING, ChunkingSettingsTests.createRandomChunkingSettings()); } diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/amazonbedrock/AmazonBedrockServiceTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/amazonbedrock/AmazonBedrockServiceTests.java index e76fb10c96131..e583e50075ee7 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/amazonbedrock/AmazonBedrockServiceTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/amazonbedrock/AmazonBedrockServiceTests.java @@ -50,6 +50,7 @@ import org.elasticsearch.xpack.inference.services.amazonbedrock.embeddings.AmazonBedrockEmbeddingsModel; import org.elasticsearch.xpack.inference.services.amazonbedrock.embeddings.AmazonBedrockEmbeddingsModelTests; import org.elasticsearch.xpack.inference.services.amazonbedrock.embeddings.AmazonBedrockEmbeddingsServiceSettings; +import org.elasticsearch.xpack.inference.services.settings.RateLimitSettingsTests; import org.hamcrest.CoreMatchers; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; @@ -72,6 +73,7 @@ import static org.elasticsearch.xpack.inference.results.ChatCompletionResultsTests.buildExpectationCompletion; import static org.elasticsearch.xpack.inference.results.TextEmbeddingResultsTests.buildExpectationFloat; import static org.elasticsearch.xpack.inference.services.ServiceComponentsTests.createWithEmptySettings; +import static org.elasticsearch.xpack.inference.services.amazonbedrock.AmazonBedrockProviderCapabilities.getProviderDefaultSimilarityMeasure; import static org.elasticsearch.xpack.inference.services.amazonbedrock.AmazonBedrockSecretSettingsTests.getAmazonBedrockSecretSettingsMap; import static org.elasticsearch.xpack.inference.services.amazonbedrock.completion.AmazonBedrockChatCompletionServiceSettingsTests.createChatCompletionRequestSettingsMap; import static org.elasticsearch.xpack.inference.services.amazonbedrock.completion.AmazonBedrockChatCompletionTaskSettingsTests.getChatCompletionTaskSettingsMap; @@ -1375,6 +1377,78 @@ public void testCheckModelConfig_ReturnsNewModelReference_AndDoesNotSendDimensio } } + public void testUpdateModelWithEmbeddingDetails_InvalidModelProvided() throws IOException { + var sender = mock(Sender.class); + var factory = mock(HttpRequestSender.Factory.class); + when(factory.createSender()).thenReturn(sender); + + var amazonBedrockFactory = new AmazonBedrockMockRequestSender.Factory( + ServiceComponentsTests.createWithSettings(threadPool, Settings.EMPTY), + mockClusterServiceEmpty() + ); + + try (var service = new AmazonBedrockService(factory, amazonBedrockFactory, createWithEmptySettings(threadPool))) { + var model = AmazonBedrockChatCompletionModelTests.createModel( + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomFrom(AmazonBedrockProvider.values()), + randomAlphaOfLength(10), + randomAlphaOfLength(10) + ); + assertThrows( + ElasticsearchStatusException.class, + () -> { service.updateModelWithEmbeddingDetails(model, randomNonNegativeInt()); } + ); + } + } + + public void testUpdateModelWithEmbeddingDetails_NullSimilarityInOriginalModel() throws IOException { + testUpdateModelWithEmbeddingDetails_Successful(null); + } + + public void testUpdateModelWithEmbeddingDetails_NonNullSimilarityInOriginalModel() throws IOException { + testUpdateModelWithEmbeddingDetails_Successful(randomFrom(SimilarityMeasure.values())); + } + + private void testUpdateModelWithEmbeddingDetails_Successful(SimilarityMeasure similarityMeasure) throws IOException { + var sender = mock(Sender.class); + var factory = mock(HttpRequestSender.Factory.class); + when(factory.createSender()).thenReturn(sender); + + var amazonBedrockFactory = new AmazonBedrockMockRequestSender.Factory( + ServiceComponentsTests.createWithSettings(threadPool, Settings.EMPTY), + mockClusterServiceEmpty() + ); + + try (var service = new AmazonBedrockService(factory, amazonBedrockFactory, createWithEmptySettings(threadPool))) { + var embeddingSize = randomNonNegativeInt(); + var provider = randomFrom(AmazonBedrockProvider.values()); + var model = AmazonBedrockEmbeddingsModelTests.createModel( + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + provider, + randomNonNegativeInt(), + randomBoolean(), + randomNonNegativeInt(), + similarityMeasure, + RateLimitSettingsTests.createRandom(), + createRandomChunkingSettings(), + randomAlphaOfLength(10), + randomAlphaOfLength(10) + ); + + Model updatedModel = service.updateModelWithEmbeddingDetails(model, embeddingSize); + + SimilarityMeasure expectedSimilarityMeasure = similarityMeasure == null + ? getProviderDefaultSimilarityMeasure(provider) + : similarityMeasure; + assertEquals(expectedSimilarityMeasure, updatedModel.getServiceSettings().similarity()); + assertEquals(embeddingSize, updatedModel.getServiceSettings().dimensions().intValue()); + } + } + public void testInfer_UnauthorizedResponse() throws IOException { var sender = mock(Sender.class); var factory = mock(HttpRequestSender.Factory.class); diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiServiceTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiServiceTests.java index 40f8b7e0977e4..dc1970e26a3f8 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiServiceTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/azureopenai/AzureOpenAiServiceTests.java @@ -1194,6 +1194,53 @@ public void testCheckModelConfig_ReturnsNewModelReference_AndDoesNotSendDimensio } } + public void testUpdateModelWithEmbeddingDetails_InvalidModelProvided() throws IOException { + var senderFactory = HttpRequestSenderTests.createSenderFactory(threadPool, clientManager); + + try (var service = new AzureOpenAiService(senderFactory, createWithEmptySettings(threadPool))) { + var model = AzureOpenAiCompletionModelTests.createModelWithRandomValues(); + assertThrows( + ElasticsearchStatusException.class, + () -> { service.updateModelWithEmbeddingDetails(model, randomNonNegativeInt()); } + ); + } + } + + public void testUpdateModelWithEmbeddingDetails_NullSimilarityInOriginalModel() throws IOException { + testUpdateModelWithEmbeddingDetails_Successful(null); + } + + public void testUpdateModelWithEmbeddingDetails_NonNullSimilarityInOriginalModel() throws IOException { + testUpdateModelWithEmbeddingDetails_Successful(randomFrom(SimilarityMeasure.values())); + } + + private void testUpdateModelWithEmbeddingDetails_Successful(SimilarityMeasure similarityMeasure) throws IOException { + var senderFactory = HttpRequestSenderTests.createSenderFactory(threadPool, clientManager); + + try (var service = new AzureOpenAiService(senderFactory, createWithEmptySettings(threadPool))) { + var embeddingSize = randomNonNegativeInt(); + var model = AzureOpenAiEmbeddingsModelTests.createModel( + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomNonNegativeInt(), + randomBoolean(), + randomNonNegativeInt(), + similarityMeasure, + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10) + ); + + Model updatedModel = service.updateModelWithEmbeddingDetails(model, embeddingSize); + + SimilarityMeasure expectedSimilarityMeasure = similarityMeasure == null ? SimilarityMeasure.DOT_PRODUCT : similarityMeasure; + assertEquals(expectedSimilarityMeasure, updatedModel.getServiceSettings().similarity()); + assertEquals(embeddingSize, updatedModel.getServiceSettings().dimensions().intValue()); + } + } + public void testInfer_UnauthorisedResponse() throws IOException, URISyntaxException { var senderFactory = HttpRequestSenderTests.createSenderFactory(threadPool, clientManager); diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/cohere/CohereServiceTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/cohere/CohereServiceTests.java index 725879e76efc1..30f3b344a268c 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/cohere/CohereServiceTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/cohere/CohereServiceTests.java @@ -1074,6 +1074,50 @@ public void testCheckModelConfig_DoesNotUpdateSimilarity_WhenItIsSpecifiedAsCosi } } + public void testUpdateModelWithEmbeddingDetails_InvalidModelProvided() throws IOException { + var senderFactory = HttpRequestSenderTests.createSenderFactory(threadPool, clientManager); + + try (var service = new CohereService(senderFactory, createWithEmptySettings(threadPool))) { + var model = CohereCompletionModelTests.createModel(randomAlphaOfLength(10), randomAlphaOfLength(10), randomAlphaOfLength(10)); + assertThrows( + ElasticsearchStatusException.class, + () -> { service.updateModelWithEmbeddingDetails(model, randomNonNegativeInt()); } + ); + } + } + + public void testUpdateModelWithEmbeddingDetails_NullSimilarityInOriginalModel() throws IOException { + testUpdateModelWithEmbeddingDetails_Successful(null); + } + + public void testUpdateModelWithEmbeddingDetails_NonNullSimilarityInOriginalModel() throws IOException { + testUpdateModelWithEmbeddingDetails_Successful(randomFrom(SimilarityMeasure.values())); + } + + private void testUpdateModelWithEmbeddingDetails_Successful(SimilarityMeasure similarityMeasure) throws IOException { + var senderFactory = HttpRequestSenderTests.createSenderFactory(threadPool, clientManager); + + try (var service = new CohereService(senderFactory, createWithEmptySettings(threadPool))) { + var embeddingSize = randomNonNegativeInt(); + var model = CohereEmbeddingsModelTests.createModel( + randomAlphaOfLength(10), + randomAlphaOfLength(10), + CohereEmbeddingsTaskSettings.EMPTY_SETTINGS, + randomNonNegativeInt(), + randomNonNegativeInt(), + randomAlphaOfLength(10), + randomFrom(CohereEmbeddingType.values()), + similarityMeasure + ); + + Model updatedModel = service.updateModelWithEmbeddingDetails(model, embeddingSize); + + SimilarityMeasure expectedSimilarityMeasure = similarityMeasure == null ? CohereService.defaultSimilarity() : similarityMeasure; + assertEquals(expectedSimilarityMeasure, updatedModel.getServiceSettings().similarity()); + assertEquals(embeddingSize, updatedModel.getServiceSettings().dimensions().intValue()); + } + } + public void testInfer_UnauthorisedResponse() throws IOException { var senderFactory = HttpRequestSenderTests.createSenderFactory(threadPool, clientManager); diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/googlevertexai/GoogleVertexAiServiceTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/googlevertexai/GoogleVertexAiServiceTests.java index 906a825e49561..2aeba5fcbe209 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/googlevertexai/GoogleVertexAiServiceTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/googlevertexai/GoogleVertexAiServiceTests.java @@ -19,6 +19,7 @@ import org.elasticsearch.inference.InputType; import org.elasticsearch.inference.Model; import org.elasticsearch.inference.ModelConfigurations; +import org.elasticsearch.inference.SimilarityMeasure; import org.elasticsearch.inference.TaskType; import org.elasticsearch.test.ESTestCase; import org.elasticsearch.test.http.MockWebServer; @@ -30,9 +31,11 @@ import org.elasticsearch.xpack.inference.logging.ThrottlerManager; import org.elasticsearch.xpack.inference.services.ServiceFields; import org.elasticsearch.xpack.inference.services.googlevertexai.embeddings.GoogleVertexAiEmbeddingsModel; +import org.elasticsearch.xpack.inference.services.googlevertexai.embeddings.GoogleVertexAiEmbeddingsModelTests; import org.elasticsearch.xpack.inference.services.googlevertexai.embeddings.GoogleVertexAiEmbeddingsServiceSettings; import org.elasticsearch.xpack.inference.services.googlevertexai.embeddings.GoogleVertexAiEmbeddingsTaskSettings; import org.elasticsearch.xpack.inference.services.googlevertexai.rerank.GoogleVertexAiRerankModel; +import org.elasticsearch.xpack.inference.services.googlevertexai.rerank.GoogleVertexAiRerankModelTests; import org.elasticsearch.xpack.inference.services.googlevertexai.rerank.GoogleVertexAiRerankTaskSettings; import org.hamcrest.CoreMatchers; import org.hamcrest.Matchers; @@ -827,6 +830,37 @@ public void testParsePersistedConfig_CreatesAnEmbeddingsModelWhenChunkingSetting } } + public void testUpdateModelWithEmbeddingDetails_InvalidModelProvided() throws IOException { + try (var service = createGoogleVertexAiService()) { + var model = GoogleVertexAiRerankModelTests.createModel(randomAlphaOfLength(10), randomNonNegativeInt()); + assertThrows( + ElasticsearchStatusException.class, + () -> { service.updateModelWithEmbeddingDetails(model, randomNonNegativeInt()); } + ); + } + } + + public void testUpdateModelWithEmbeddingDetails_NullSimilarityInOriginalModel() throws IOException { + testUpdateModelWithEmbeddingDetails_Successful(null); + } + + public void testUpdateModelWithEmbeddingDetails_NonNullSimilarityInOriginalModel() throws IOException { + testUpdateModelWithEmbeddingDetails_Successful(randomFrom(SimilarityMeasure.values())); + } + + private void testUpdateModelWithEmbeddingDetails_Successful(SimilarityMeasure similarityMeasure) throws IOException { + try (var service = createGoogleVertexAiService()) { + var embeddingSize = randomNonNegativeInt(); + var model = GoogleVertexAiEmbeddingsModelTests.createModel(randomAlphaOfLength(10), randomBoolean(), similarityMeasure); + + Model updatedModel = service.updateModelWithEmbeddingDetails(model, embeddingSize); + + SimilarityMeasure expectedSimilarityMeasure = similarityMeasure == null ? SimilarityMeasure.DOT_PRODUCT : similarityMeasure; + assertEquals(expectedSimilarityMeasure, updatedModel.getServiceSettings().similarity()); + assertEquals(embeddingSize, updatedModel.getServiceSettings().dimensions().intValue()); + } + } + // testInfer tested via end-to-end notebook tests in AppEx repo @SuppressWarnings("checkstyle:LineLength") diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/googlevertexai/embeddings/GoogleVertexAiEmbeddingsModelTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/googlevertexai/embeddings/GoogleVertexAiEmbeddingsModelTests.java index 7836c5c15cfb1..5b016de7493f5 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/googlevertexai/embeddings/GoogleVertexAiEmbeddingsModelTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/googlevertexai/embeddings/GoogleVertexAiEmbeddingsModelTests.java @@ -64,7 +64,7 @@ public void testOverrideWith_DoesNotOverrideAndModelRemainsEqual_WhenSettingsAre } public void testOverrideWith_SetsInputTypeToOverride_WhenFieldIsNullInModelTaskSettings_AndNullInRequestTaskSettings() { - var model = createModel("model", Boolean.FALSE, null); + var model = createModel("model", Boolean.FALSE, (InputType) null); var overriddenModel = GoogleVertexAiEmbeddingsModel.of(model, getTaskSettingsMap(null, null), InputType.SEARCH); var expectedModel = createModel("model", Boolean.FALSE, InputType.SEARCH); @@ -80,7 +80,7 @@ public void testOverrideWith_SetsInputType_FromRequest_IfValid_OverridingStoredT } public void testOverrideWith_SetsInputType_FromRequest_IfValid_OverridingRequestTaskSettings() { - var model = createModel("model", Boolean.FALSE, null); + var model = createModel("model", Boolean.FALSE, (InputType) null); var overriddenModel = GoogleVertexAiEmbeddingsModel.of(model, getTaskSettingsMap(null, InputType.CLUSTERING), InputType.SEARCH); var expectedModel = createModel("model", Boolean.FALSE, InputType.SEARCH); @@ -96,10 +96,10 @@ public void testOverrideWith_OverridesInputType_WithRequestTaskSettingsSearch_Wh } public void testOverrideWith_DoesNotSetInputType_FromRequest_IfInputTypeIsInvalid() { - var model = createModel("model", Boolean.FALSE, null); + var model = createModel("model", Boolean.FALSE, (InputType) null); var overriddenModel = GoogleVertexAiEmbeddingsModel.of(model, getTaskSettingsMap(null, null), InputType.UNSPECIFIED); - var expectedModel = createModel("model", Boolean.FALSE, null); + var expectedModel = createModel("model", Boolean.FALSE, (InputType) null); MatcherAssert.assertThat(overriddenModel, is(expectedModel)); } @@ -136,6 +136,31 @@ public static GoogleVertexAiEmbeddingsModel createModel( ); } + public static GoogleVertexAiEmbeddingsModel createModel( + String modelId, + @Nullable Boolean autoTruncate, + SimilarityMeasure similarityMeasure + ) { + return new GoogleVertexAiEmbeddingsModel( + "id", + TaskType.TEXT_EMBEDDING, + "service", + new GoogleVertexAiEmbeddingsServiceSettings( + randomAlphaOfLength(8), + randomAlphaOfLength(8), + modelId, + false, + null, + null, + similarityMeasure, + null + ), + new GoogleVertexAiEmbeddingsTaskSettings(autoTruncate, randomFrom(InputType.INGEST, InputType.SEARCH)), + null, + new GoogleVertexAiSecretSettings(new SecureString(randomAlphaOfLength(8).toCharArray())) + ); + } + public static GoogleVertexAiEmbeddingsModel createModel(String modelId, @Nullable Boolean autoTruncate, @Nullable InputType inputType) { return new GoogleVertexAiEmbeddingsModel( "id", diff --git a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/ibmwatsonx/IbmWatsonxServiceTests.java b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/ibmwatsonx/IbmWatsonxServiceTests.java index f7f37c5bcd15f..1261e3834437b 100644 --- a/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/ibmwatsonx/IbmWatsonxServiceTests.java +++ b/x-pack/plugin/inference/src/test/java/org/elasticsearch/xpack/inference/services/ibmwatsonx/IbmWatsonxServiceTests.java @@ -51,6 +51,7 @@ import org.elasticsearch.xpack.inference.services.ServiceFields; import org.elasticsearch.xpack.inference.services.ibmwatsonx.embeddings.IbmWatsonxEmbeddingsModel; import org.elasticsearch.xpack.inference.services.ibmwatsonx.embeddings.IbmWatsonxEmbeddingsModelTests; +import org.elasticsearch.xpack.inference.services.openai.completion.OpenAiChatCompletionModelTests; import org.hamcrest.MatcherAssert; import org.hamcrest.Matchers; import org.junit.After; @@ -930,6 +931,56 @@ public void testCheckModelConfig_DoesNotUpdateSimilarity_WhenItIsSpecifiedAsCosi } } + public void testUpdateModelWithEmbeddingDetails_InvalidModelProvided() throws IOException { + var senderFactory = HttpRequestSenderTests.createSenderFactory(threadPool, clientManager); + + try (var service = new IbmWatsonxServiceWithoutAuth(senderFactory, createWithEmptySettings(threadPool))) { + var model = OpenAiChatCompletionModelTests.createChatCompletionModel( + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10) + ); + assertThrows( + ElasticsearchStatusException.class, + () -> { service.updateModelWithEmbeddingDetails(model, randomNonNegativeInt()); } + ); + } + } + + public void testUpdateModelWithEmbeddingDetails_NullSimilarityInOriginalModel() throws IOException { + testUpdateModelWithEmbeddingDetails_Successful(null); + } + + public void testUpdateModelWithEmbeddingDetails_NonNullSimilarityInOriginalModel() throws IOException { + testUpdateModelWithEmbeddingDetails_Successful(randomFrom(SimilarityMeasure.values())); + } + + private void testUpdateModelWithEmbeddingDetails_Successful(SimilarityMeasure similarityMeasure) throws IOException { + var senderFactory = HttpRequestSenderTests.createSenderFactory(threadPool, clientManager); + + try (var service = new IbmWatsonxServiceWithoutAuth(senderFactory, createWithEmptySettings(threadPool))) { + var embeddingSize = randomNonNegativeInt(); + var model = IbmWatsonxEmbeddingsModelTests.createModel( + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + URI.create(randomAlphaOfLength(10)), + randomAlphaOfLength(10), + randomAlphaOfLength(10), + randomNonNegativeInt(), + similarityMeasure + ); + + Model updatedModel = service.updateModelWithEmbeddingDetails(model, embeddingSize); + + SimilarityMeasure expectedSimilarityMeasure = similarityMeasure == null ? SimilarityMeasure.DOT_PRODUCT : similarityMeasure; + assertEquals(expectedSimilarityMeasure, updatedModel.getServiceSettings().similarity()); + assertEquals(embeddingSize, updatedModel.getServiceSettings().dimensions().intValue()); + } + } + public void testGetConfiguration() throws Exception { try (var service = createIbmWatsonxService()) { String content = XContentHelper.stripWhitespace(""" From 2f0b095b5d7ce9adcd6c37682e39c277ad5cb512 Mon Sep 17 00:00:00 2001 From: Martijn van Groningen Date: Mon, 25 Nov 2024 16:45:36 +0100 Subject: [PATCH 20/34] Stop using _source.mode attribute in traces-otel builtin template (#117487) The traces-otel@mappings component template is configured to use logsdb. No need to configure source mode separately. --- .../resources/component-templates/traces-otel@mappings.yaml | 2 -- x-pack/plugin/otel-data/src/main/resources/resources.yaml | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/x-pack/plugin/otel-data/src/main/resources/component-templates/traces-otel@mappings.yaml b/x-pack/plugin/otel-data/src/main/resources/component-templates/traces-otel@mappings.yaml index 2b0d1ec536fa6..3a1ba435b8f1f 100644 --- a/x-pack/plugin/otel-data/src/main/resources/component-templates/traces-otel@mappings.yaml +++ b/x-pack/plugin/otel-data/src/main/resources/component-templates/traces-otel@mappings.yaml @@ -10,8 +10,6 @@ template: sort: field: [ "resource.attributes.host.name", "@timestamp" ] mappings: - _source: - mode: synthetic properties: trace_id: type: keyword diff --git a/x-pack/plugin/otel-data/src/main/resources/resources.yaml b/x-pack/plugin/otel-data/src/main/resources/resources.yaml index b2d30c7f85cc4..9edbe5622b3f1 100644 --- a/x-pack/plugin/otel-data/src/main/resources/resources.yaml +++ b/x-pack/plugin/otel-data/src/main/resources/resources.yaml @@ -1,7 +1,7 @@ # "version" holds the version of the templates and ingest pipelines installed # by xpack-plugin otel-data. This must be increased whenever an existing template is # changed, in order for it to be updated on Elasticsearch upgrade. -version: 6 +version: 7 component-templates: - otel@mappings From b7d801809fce6669aaa530f7375bfdc6a6bcb24e Mon Sep 17 00:00:00 2001 From: padmaprasath21 <168728638+padmaprasath21@users.noreply.github.com> Date: Mon, 25 Nov 2024 21:26:17 +0530 Subject: [PATCH 21/34] Update tsds-reindex.asciidoc (#117446) --- docs/reference/data-streams/tsds-reindex.asciidoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/reference/data-streams/tsds-reindex.asciidoc b/docs/reference/data-streams/tsds-reindex.asciidoc index 9d6594db4e779..f4d00f33c179c 100644 --- a/docs/reference/data-streams/tsds-reindex.asciidoc +++ b/docs/reference/data-streams/tsds-reindex.asciidoc @@ -202,7 +202,7 @@ POST /_component_template/destination_template POST /_index_template/2 { "index_patterns": [ - "k8s*" + "k9s*" ], "composed_of": [ "destination_template" From 8c22fc479f7f62e1ac6ce2e6db30c1c723ab3c8f Mon Sep 17 00:00:00 2001 From: Craig Taverner Date: Mon, 25 Nov 2024 17:04:48 +0100 Subject: [PATCH 22/34] Make spatial search functions not preview (#117489) --- .../esql/functions/spatial-functions.asciidoc | 16 ++++++++-------- docs/reference/geospatial-analysis.asciidoc | 10 +++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/reference/esql/functions/spatial-functions.asciidoc b/docs/reference/esql/functions/spatial-functions.asciidoc index 79acc2028d983..eee44d337b4c6 100644 --- a/docs/reference/esql/functions/spatial-functions.asciidoc +++ b/docs/reference/esql/functions/spatial-functions.asciidoc @@ -8,19 +8,19 @@ {esql} supports these spatial functions: // tag::spatial_list[] -* experimental:[] <> -* experimental:[] <> -* experimental:[] <> -* experimental:[] <> -* experimental:[] <> -* experimental:[] <> -* experimental:[] <> +* <> +* <> +* <> +* <> +* <> +* <> +* <> // end::spatial_list[] +include::layout/st_distance.asciidoc[] include::layout/st_intersects.asciidoc[] include::layout/st_disjoint.asciidoc[] include::layout/st_contains.asciidoc[] include::layout/st_within.asciidoc[] include::layout/st_x.asciidoc[] include::layout/st_y.asciidoc[] -include::layout/st_distance.asciidoc[] diff --git a/docs/reference/geospatial-analysis.asciidoc b/docs/reference/geospatial-analysis.asciidoc index 6760040e14bc7..678e0ee17aec2 100644 --- a/docs/reference/geospatial-analysis.asciidoc +++ b/docs/reference/geospatial-analysis.asciidoc @@ -38,11 +38,11 @@ Data is often messy and incomplete. <> lets you clean, <> has support for <> functions, enabling efficient index searching for documents that intersect with, are within, are contained by, or are disjoint from a query geometry. In addition, the `ST_DISTANCE` function calculates the distance between two points. -* experimental:[] <> -* experimental:[] <> -* experimental:[] <> -* experimental:[] <> -* experimental:[] <> +* <> +* <> +* <> +* <> +* <> [discrete] [[geospatial-aggregate]] From 4e3301530d16ff937fa835b42a108aee48203af5 Mon Sep 17 00:00:00 2001 From: David Kyle Date: Mon, 25 Nov 2024 16:20:18 +0000 Subject: [PATCH 23/34] [ML] Explicitly set chunking settings in preconfigured endpoints (#117327) --- .../xpack/inference/DefaultEndPointsIT.java | 20 +++++++++++++++++++ .../ElasticsearchInternalService.java | 5 +++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/x-pack/plugin/inference/qa/inference-service-tests/src/javaRestTest/java/org/elasticsearch/xpack/inference/DefaultEndPointsIT.java b/x-pack/plugin/inference/qa/inference-service-tests/src/javaRestTest/java/org/elasticsearch/xpack/inference/DefaultEndPointsIT.java index 69767ce0b24f0..ba3e48e11928d 100644 --- a/x-pack/plugin/inference/qa/inference-service-tests/src/javaRestTest/java/org/elasticsearch/xpack/inference/DefaultEndPointsIT.java +++ b/x-pack/plugin/inference/qa/inference-service-tests/src/javaRestTest/java/org/elasticsearch/xpack/inference/DefaultEndPointsIT.java @@ -51,6 +51,14 @@ public void tearDown() throws Exception { super.tearDown(); } + public void testGet() throws IOException { + var elserModel = getModel(ElasticsearchInternalService.DEFAULT_ELSER_ID); + assertDefaultElserConfig(elserModel); + + var e5Model = getModel(ElasticsearchInternalService.DEFAULT_E5_ID); + assertDefaultE5Config(e5Model); + } + @SuppressWarnings("unchecked") public void testInferDeploysDefaultElser() throws IOException { var model = getModel(ElasticsearchInternalService.DEFAULT_ELSER_ID); @@ -79,6 +87,7 @@ private static void assertDefaultElserConfig(Map modelConfig) { adaptiveAllocations, Matchers.is(Map.of("enabled", true, "min_number_of_allocations", 0, "max_number_of_allocations", 32)) ); + assertDefaultChunkingSettings(modelConfig); } @SuppressWarnings("unchecked") @@ -113,6 +122,17 @@ private static void assertDefaultE5Config(Map modelConfig) { adaptiveAllocations, Matchers.is(Map.of("enabled", true, "min_number_of_allocations", 0, "max_number_of_allocations", 32)) ); + assertDefaultChunkingSettings(modelConfig); + } + + @SuppressWarnings("unchecked") + private static void assertDefaultChunkingSettings(Map modelConfig) { + var chunkingSettings = (Map) modelConfig.get("chunking_settings"); + assertThat( + modelConfig.toString(), + chunkingSettings, + Matchers.is(Map.of("strategy", "sentence", "max_chunk_size", 250, "sentence_overlap", 1)) + ); } public void testMultipleInferencesTriggeringDownloadAndDeploy() throws InterruptedException { diff --git a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/elasticsearch/ElasticsearchInternalService.java b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/elasticsearch/ElasticsearchInternalService.java index 718aeae979fe9..6d124906d65bd 100644 --- a/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/elasticsearch/ElasticsearchInternalService.java +++ b/x-pack/plugin/inference/src/main/java/org/elasticsearch/xpack/inference/services/elasticsearch/ElasticsearchInternalService.java @@ -862,6 +862,7 @@ public void updateModelsWithDynamicFields(List models, ActionListener> defaultsListener) { preferredModelVariantFn.accept(defaultsListener.delegateFailureAndWrap((delegate, preferredModelVariant) -> { if (PreferredModelVariant.LINUX_X86_OPTIMIZED.equals(preferredModelVariant)) { @@ -892,7 +893,7 @@ private List defaultConfigs(boolean useLinuxOptimizedModel) { new AdaptiveAllocationsSettings(Boolean.TRUE, 0, 32) ), ElserMlNodeTaskSettings.DEFAULT, - null // default chunking settings + ChunkingSettingsBuilder.DEFAULT_SETTINGS ); var defaultE5 = new MultilingualE5SmallModel( DEFAULT_E5_ID, @@ -904,7 +905,7 @@ private List defaultConfigs(boolean useLinuxOptimizedModel) { useLinuxOptimizedModel ? MULTILINGUAL_E5_SMALL_MODEL_ID_LINUX_X86 : MULTILINGUAL_E5_SMALL_MODEL_ID, new AdaptiveAllocationsSettings(Boolean.TRUE, 0, 32) ), - null // default chunking settings + ChunkingSettingsBuilder.DEFAULT_SETTINGS ); return List.of(defaultElser, defaultE5); } From 374c88a832edb53525a1c52873db185c2acdfb23 Mon Sep 17 00:00:00 2001 From: Benjamin Trent Date: Mon, 25 Nov 2024 11:38:06 -0500 Subject: [PATCH 24/34] Correct bit * byte and bit * float script comparisons (#117404) I goofed on the bit * byte and bit * float comparisons. Naturally, these should be bigendian and compare the dimensions with the binary ones appropriately. Additionally, I added a test to ensure that this is handled correctly. --- docs/changelog/117404.yaml | 5 +++ .../vectors/vector-functions.asciidoc | 4 ++ .../elasticsearch/simdvec/ESVectorUtil.java | 12 ++++-- .../simdvec/ESVectorUtilTests.java | 16 +++++++ .../141_multi_dense_vector_max_sim.yml | 6 +-- .../painless/146_dense_vector_bit_basic.yml | 42 +++++++++---------- .../action/search/SearchCapabilities.java | 4 +- .../MultiVectorScoreScriptUtilsTests.java | 2 +- .../script/VectorScoreScriptUtilsTests.java | 2 +- 9 files changed, 61 insertions(+), 32 deletions(-) create mode 100644 docs/changelog/117404.yaml diff --git a/docs/changelog/117404.yaml b/docs/changelog/117404.yaml new file mode 100644 index 0000000000000..0bab171956ca9 --- /dev/null +++ b/docs/changelog/117404.yaml @@ -0,0 +1,5 @@ +pr: 117404 +summary: Correct bit * byte and bit * float script comparisons +area: Vector Search +type: bug +issues: [] diff --git a/docs/reference/vectors/vector-functions.asciidoc b/docs/reference/vectors/vector-functions.asciidoc index 10dca8084e28a..23419e8eb12b1 100644 --- a/docs/reference/vectors/vector-functions.asciidoc +++ b/docs/reference/vectors/vector-functions.asciidoc @@ -336,6 +336,10 @@ When using `bit` vectors, not all the vector functions are available. The suppor this is the sum of the bitwise AND of the two vectors. If providing `float[]` or `byte[]`, who has `dims` number of elements, as a query vector, the `dotProduct` is the sum of the floating point values using the stored `bit` vector as a mask. +NOTE: When comparing `floats` and `bytes` with `bit` vectors, the `bit` vector is treated as a mask in big-endian order. +For example, if the `bit` vector is `10100001` (e.g. the single byte value `161`) and its compared +with array of values `[1, 2, 3, 4, 5, 6, 7, 8]` the `dotProduct` will be `1 + 3 + 8 = 16`. + Here is an example of using dot-product with bit vectors. [source,console] diff --git a/libs/simdvec/src/main/java/org/elasticsearch/simdvec/ESVectorUtil.java b/libs/simdvec/src/main/java/org/elasticsearch/simdvec/ESVectorUtil.java index de2cb9042610b..2f4743a47a14a 100644 --- a/libs/simdvec/src/main/java/org/elasticsearch/simdvec/ESVectorUtil.java +++ b/libs/simdvec/src/main/java/org/elasticsearch/simdvec/ESVectorUtil.java @@ -51,6 +51,8 @@ public static long ipByteBinByte(byte[] q, byte[] d) { /** * Compute the inner product of two vectors, where the query vector is a byte vector and the document vector is a bit vector. * This will return the sum of the query vector values using the document vector as a mask. + * When comparing the bits with the bytes, they are done in "big endian" order. For example, if the byte vector + * is [1, 2, 3, 4, 5, 6, 7, 8] and the bit vector is [0b10000000], the inner product will be 1.0. * @param q the query vector * @param d the document vector * @return the inner product of the two vectors @@ -63,9 +65,9 @@ public static int ipByteBit(byte[] q, byte[] d) { // now combine the two vectors, summing the byte dimensions where the bit in d is `1` for (int i = 0; i < d.length; i++) { byte mask = d[i]; - for (int j = 0; j < Byte.SIZE; j++) { + for (int j = Byte.SIZE - 1; j >= 0; j--) { if ((mask & (1 << j)) != 0) { - result += q[i * Byte.SIZE + j]; + result += q[i * Byte.SIZE + Byte.SIZE - 1 - j]; } } } @@ -75,6 +77,8 @@ public static int ipByteBit(byte[] q, byte[] d) { /** * Compute the inner product of two vectors, where the query vector is a float vector and the document vector is a bit vector. * This will return the sum of the query vector values using the document vector as a mask. + * When comparing the bits with the floats, they are done in "big endian" order. For example, if the float vector + * is [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0] and the bit vector is [0b10000000], the inner product will be 1.0. * @param q the query vector * @param d the document vector * @return the inner product of the two vectors @@ -86,9 +90,9 @@ public static float ipFloatBit(float[] q, byte[] d) { float result = 0; for (int i = 0; i < d.length; i++) { byte mask = d[i]; - for (int j = 0; j < Byte.SIZE; j++) { + for (int j = Byte.SIZE - 1; j >= 0; j--) { if ((mask & (1 << j)) != 0) { - result += q[i * Byte.SIZE + j]; + result += q[i * Byte.SIZE + Byte.SIZE - 1 - j]; } } } diff --git a/libs/simdvec/src/test/java/org/elasticsearch/simdvec/ESVectorUtilTests.java b/libs/simdvec/src/test/java/org/elasticsearch/simdvec/ESVectorUtilTests.java index e9e0fd58f7638..368898b934c87 100644 --- a/libs/simdvec/src/test/java/org/elasticsearch/simdvec/ESVectorUtilTests.java +++ b/libs/simdvec/src/test/java/org/elasticsearch/simdvec/ESVectorUtilTests.java @@ -21,6 +21,22 @@ public class ESVectorUtilTests extends BaseVectorizationTests { static final ESVectorizationProvider defaultedProvider = BaseVectorizationTests.defaultProvider(); static final ESVectorizationProvider defOrPanamaProvider = BaseVectorizationTests.maybePanamaProvider(); + public void testIpByteBit() { + byte[] q = new byte[16]; + byte[] d = new byte[] { (byte) Integer.parseInt("01100010", 2), (byte) Integer.parseInt("10100111", 2) }; + random().nextBytes(q); + int expected = q[1] + q[2] + q[6] + q[8] + q[10] + q[13] + q[14] + q[15]; + assertEquals(expected, ESVectorUtil.ipByteBit(q, d)); + } + + public void testIpFloatBit() { + float[] q = new float[16]; + byte[] d = new byte[] { (byte) Integer.parseInt("01100010", 2), (byte) Integer.parseInt("10100111", 2) }; + random().nextFloat(); + float expected = q[1] + q[2] + q[6] + q[8] + q[10] + q[13] + q[14] + q[15]; + assertEquals(expected, ESVectorUtil.ipFloatBit(q, d), 1e-6); + } + public void testBitAndCount() { testBasicBitAndImpl(ESVectorUtil::andBitCountLong); } diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/141_multi_dense_vector_max_sim.yml b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/141_multi_dense_vector_max_sim.yml index caa7c59ab4c42..77d4b70cdfcae 100644 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/141_multi_dense_vector_max_sim.yml +++ b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/141_multi_dense_vector_max_sim.yml @@ -3,7 +3,7 @@ setup: capabilities: - method: POST path: /_search - capabilities: [ multi_dense_vector_script_max_sim ] + capabilities: [ multi_dense_vector_script_max_sim_with_bugfix ] test_runner_features: capabilities reason: "Support for multi dense vector max-sim functions capability required" - skip: @@ -136,10 +136,10 @@ setup: - match: {hits.total: 2} - match: {hits.hits.0._id: "1"} - - close_to: {hits.hits.0._score: {value: 190, error: 0.01}} + - close_to: {hits.hits.0._score: {value: 220, error: 0.01}} - match: {hits.hits.1._id: "3"} - - close_to: {hits.hits.1._score: {value: 125, error: 0.01}} + - close_to: {hits.hits.1._score: {value: 147, error: 0.01}} --- "Test max-sim inv hamming scoring": - skip: diff --git a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/146_dense_vector_bit_basic.yml b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/146_dense_vector_bit_basic.yml index 2ee38f849e9d4..cdd65ca0eb296 100644 --- a/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/146_dense_vector_bit_basic.yml +++ b/modules/lang-painless/src/yamlRestTest/resources/rest-api-spec/test/painless/146_dense_vector_bit_basic.yml @@ -108,7 +108,7 @@ setup: capabilities: - method: POST path: /_search - capabilities: [ byte_float_bit_dot_product ] + capabilities: [ byte_float_bit_dot_product_with_bugfix ] reason: Capability required to run test - do: catch: bad_request @@ -399,7 +399,7 @@ setup: capabilities: - method: POST path: /_search - capabilities: [ byte_float_bit_dot_product ] + capabilities: [ byte_float_bit_dot_product_with_bugfix ] test_runner_features: [capabilities, close_to] reason: Capability required to run test - do: @@ -419,13 +419,13 @@ setup: - match: { hits.total: 3 } - match: {hits.hits.0._id: "2"} - - close_to: {hits.hits.0._score: {value: 35.999, error: 0.01}} + - close_to: {hits.hits.0._score: {value: 33.78, error: 0.01}} - match: {hits.hits.1._id: "3"} - - close_to: {hits.hits.1._score:{value: 27.23, error: 0.01}} + - close_to: {hits.hits.1._score:{value: 22.579, error: 0.01}} - match: {hits.hits.2._id: "1"} - - close_to: {hits.hits.2._score: {value: 16.57, error: 0.01}} + - close_to: {hits.hits.2._score: {value: 11.919, error: 0.01}} - do: headers: @@ -444,20 +444,20 @@ setup: - match: { hits.total: 3 } - match: {hits.hits.0._id: "2"} - - close_to: {hits.hits.0._score: {value: 35.999, error: 0.01}} + - close_to: {hits.hits.0._score: {value: 33.78, error: 0.01}} - match: {hits.hits.1._id: "3"} - - close_to: {hits.hits.1._score:{value: 27.23, error: 0.01}} + - close_to: {hits.hits.1._score:{value: 22.579, error: 0.01}} - match: {hits.hits.2._id: "1"} - - close_to: {hits.hits.2._score: {value: 16.57, error: 0.01}} + - close_to: {hits.hits.2._score: {value: 11.919, error: 0.01}} --- "Dot product with byte": - requires: capabilities: - method: POST path: /_search - capabilities: [ byte_float_bit_dot_product ] + capabilities: [ byte_float_bit_dot_product_with_bugfix ] test_runner_features: capabilities reason: Capability required to run test - do: @@ -476,14 +476,14 @@ setup: - match: { hits.total: 3 } - - match: {hits.hits.0._id: "1"} - - match: {hits.hits.0._score: 248} + - match: {hits.hits.0._id: "3"} + - match: {hits.hits.0._score: 415} - - match: {hits.hits.1._id: "2"} - - match: {hits.hits.1._score: 136} + - match: {hits.hits.1._id: "1"} + - match: {hits.hits.1._score: 168} - - match: {hits.hits.2._id: "3"} - - match: {hits.hits.2._score: 20} + - match: {hits.hits.2._id: "2"} + - match: {hits.hits.2._score: 126} - do: headers: @@ -501,11 +501,11 @@ setup: - match: { hits.total: 3 } - - match: {hits.hits.0._id: "1"} - - match: {hits.hits.0._score: 248} + - match: {hits.hits.0._id: "3"} + - match: {hits.hits.0._score: 415} - - match: {hits.hits.1._id: "2"} - - match: {hits.hits.1._score: 136} + - match: {hits.hits.1._id: "1"} + - match: {hits.hits.1._score: 168} - - match: {hits.hits.2._id: "3"} - - match: {hits.hits.2._score: 20} + - match: {hits.hits.2._id: "2"} + - match: {hits.hits.2._score: 126} diff --git a/server/src/main/java/org/elasticsearch/rest/action/search/SearchCapabilities.java b/server/src/main/java/org/elasticsearch/rest/action/search/SearchCapabilities.java index e5c4826bfce97..794b30aa5aab2 100644 --- a/server/src/main/java/org/elasticsearch/rest/action/search/SearchCapabilities.java +++ b/server/src/main/java/org/elasticsearch/rest/action/search/SearchCapabilities.java @@ -27,7 +27,7 @@ private SearchCapabilities() {} /** Support synthetic source with `bit` type in `dense_vector` field when `index` is set to `false`. */ private static final String BIT_DENSE_VECTOR_SYNTHETIC_SOURCE_CAPABILITY = "bit_dense_vector_synthetic_source"; /** Support Byte and Float with Bit dot product. */ - private static final String BYTE_FLOAT_BIT_DOT_PRODUCT_CAPABILITY = "byte_float_bit_dot_product"; + private static final String BYTE_FLOAT_BIT_DOT_PRODUCT_CAPABILITY = "byte_float_bit_dot_product_with_bugfix"; /** Support docvalue_fields parameter for `dense_vector` field. */ private static final String DENSE_VECTOR_DOCVALUE_FIELDS = "dense_vector_docvalue_fields"; /** Support transforming rank rrf queries to the corresponding rrf retriever. */ @@ -41,7 +41,7 @@ private SearchCapabilities() {} /** Support multi-dense-vector script field access. */ private static final String MULTI_DENSE_VECTOR_SCRIPT_ACCESS = "multi_dense_vector_script_access"; /** Initial support for multi-dense-vector maxSim functions access. */ - private static final String MULTI_DENSE_VECTOR_SCRIPT_MAX_SIM = "multi_dense_vector_script_max_sim"; + private static final String MULTI_DENSE_VECTOR_SCRIPT_MAX_SIM = "multi_dense_vector_script_max_sim_with_bugfix"; private static final String RANDOM_SAMPLER_WITH_SCORED_SUBAGGS = "random_sampler_with_scored_subaggs"; diff --git a/server/src/test/java/org/elasticsearch/script/MultiVectorScoreScriptUtilsTests.java b/server/src/test/java/org/elasticsearch/script/MultiVectorScoreScriptUtilsTests.java index c4a1699181efc..f908f51170478 100644 --- a/server/src/test/java/org/elasticsearch/script/MultiVectorScoreScriptUtilsTests.java +++ b/server/src/test/java/org/elasticsearch/script/MultiVectorScoreScriptUtilsTests.java @@ -200,7 +200,7 @@ public void testBitMultiVectorClassBindingsDotProduct() throws IOException { function = new MaxSimDotProduct(scoreScript, floatQueryVector, fieldName); assertEquals( "maxSimDotProduct result is not equal to the expected value!", - 0.42f + 0f + 1f - 1f - 0.42f, + -1.4f + 0.42f + 0f + 1f - 1f, function.maxSimDotProduct(), 0.001 ); diff --git a/server/src/test/java/org/elasticsearch/script/VectorScoreScriptUtilsTests.java b/server/src/test/java/org/elasticsearch/script/VectorScoreScriptUtilsTests.java index 6b2178310d17c..dcaa64ede9e89 100644 --- a/server/src/test/java/org/elasticsearch/script/VectorScoreScriptUtilsTests.java +++ b/server/src/test/java/org/elasticsearch/script/VectorScoreScriptUtilsTests.java @@ -267,7 +267,7 @@ public void testBitVectorClassBindingsDotProduct() throws IOException { function = new DotProduct(scoreScript, floatQueryVector, fieldName); assertEquals( "dotProduct result is not equal to the expected value!", - 0.42f + 0f + 1f - 1f - 0.42f, + -1.4f + 0.42f + 0f + 1f - 1f, function.dotProduct(), 0.001 ); From 4e1807f0d91c17750c43b7bb43bc93198c61ba7f Mon Sep 17 00:00:00 2001 From: "elastic-renovate-prod[bot]" <174716857+elastic-renovate-prod[bot]@users.noreply.github.com> Date: Tue, 26 Nov 2024 03:50:16 +1100 Subject: [PATCH 25/34] Update docker.elastic.co/wolfi/chainguard-base:latest Docker digest to 55b297d (#116255) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Update | Change | |---|---|---| | docker.elastic.co/wolfi/chainguard-base | digest | `9734313` -> `55b297d` | --- ### Configuration 📅 **Schedule**: Branch creation - "after 1pm on tuesday" (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR has been generated by [Renovate Bot](https://togithub.com/renovatebot/renovate). --- .../main/java/org/elasticsearch/gradle/internal/DockerBase.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/DockerBase.java b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/DockerBase.java index bf901fef90450..71e968557cefe 100644 --- a/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/DockerBase.java +++ b/build-tools-internal/src/main/java/org/elasticsearch/gradle/internal/DockerBase.java @@ -22,7 +22,7 @@ public enum DockerBase { // Chainguard based wolfi image with latest jdk // This is usually updated via renovatebot // spotless:off - WOLFI("docker.elastic.co/wolfi/chainguard-base:latest@sha256:973431347ad45f40e01afbbd010bf9de929c088a63382239b90dd84f39618bc8", + WOLFI("docker.elastic.co/wolfi/chainguard-base:latest@sha256:55b297da5151d2a2997e8ab9729fe1304e4869389d7090ab7031cc29530f69f8", "-wolfi", "apk" ), From 631345f96531a66b9e4130c92df15f08c86e1a79 Mon Sep 17 00:00:00 2001 From: Nhat Nguyen Date: Mon, 25 Nov 2024 10:20:58 -0800 Subject: [PATCH 26/34] Adjust index version for deprecating source mode (#117183) There was a bug in the version-checking logic for emitting deprecation warnings for source.mode in mappings. --- .../DataStreamTimestampFieldMapperTests.java | 3 +- .../elasticsearch/upgrades/IndexingIT.java | 9 ++++- .../index/mapper/SourceFieldMapper.java | 13 +++++-- .../mapper/DocumentParserContextTests.java | 1 + .../index/mapper/SourceFieldMapperTests.java | 28 ++++++++++++--- .../index/shard/ShardGetServiceTests.java | 2 ++ .../index/mapper/MetadataMapperTestCase.java | 9 ++--- .../test/rest/ESRestTestCase.java | 34 +++++++++++++++---- .../xpack/deprecation/DeprecationChecks.java | 3 +- .../deprecation/IndexDeprecationChecks.java | 26 ++++++++++++++ .../compute/operator/AsyncOperator.java | 1 + .../logsdb/LogsIndexModeCustomSettingsIT.java | 15 ++++++-- .../xpack/logsdb/LogsIndexModeRestTestIT.java | 6 ++++ ...heticSourceIndexSettingsProviderTests.java | 7 +++- 14 files changed, 133 insertions(+), 24 deletions(-) diff --git a/modules/data-streams/src/test/java/org/elasticsearch/datastreams/mapper/DataStreamTimestampFieldMapperTests.java b/modules/data-streams/src/test/java/org/elasticsearch/datastreams/mapper/DataStreamTimestampFieldMapperTests.java index a3995d7462b32..e009db7209eab 100644 --- a/modules/data-streams/src/test/java/org/elasticsearch/datastreams/mapper/DataStreamTimestampFieldMapperTests.java +++ b/modules/data-streams/src/test/java/org/elasticsearch/datastreams/mapper/DataStreamTimestampFieldMapperTests.java @@ -48,7 +48,8 @@ protected void registerParameters(ParameterChecker checker) throws IOException { checker.registerConflictCheck( "enabled", timestampMapping(true, b -> b.startObject("@timestamp").field("type", "date").endObject()), - timestampMapping(false, b -> b.startObject("@timestamp").field("type", "date").endObject()) + timestampMapping(false, b -> b.startObject("@timestamp").field("type", "date").endObject()), + dm -> {} ); checker.registerUpdateCheck( timestampMapping(false, b -> b.startObject("@timestamp").field("type", "date").endObject()), diff --git a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/IndexingIT.java b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/IndexingIT.java index 090f409fd46d0..86a0151e33119 100644 --- a/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/IndexingIT.java +++ b/qa/rolling-upgrade/src/javaRestTest/java/org/elasticsearch/upgrades/IndexingIT.java @@ -20,6 +20,7 @@ import org.elasticsearch.common.xcontent.support.XContentMapValues; import org.elasticsearch.core.UpdateForV9; import org.elasticsearch.index.mapper.DateFieldMapper; +import org.elasticsearch.index.mapper.SourceFieldMapper; import org.elasticsearch.index.mapper.TimeSeriesIdFieldMapper; import org.elasticsearch.test.ListMatcher; import org.elasticsearch.xcontent.XContentBuilder; @@ -417,9 +418,15 @@ public void testSyntheticSource() throws IOException { if (isOldCluster()) { Request createIndex = new Request("PUT", "/synthetic"); XContentBuilder indexSpec = XContentBuilder.builder(XContentType.JSON.xContent()).startObject(); + boolean useIndexSetting = SourceFieldMapper.onOrAfterDeprecateModeVersion(getOldClusterIndexVersion()); + if (useIndexSetting) { + indexSpec.startObject("settings").field("index.mapping.source.mode", "synthetic").endObject(); + } indexSpec.startObject("mappings"); { - indexSpec.startObject("_source").field("mode", "synthetic").endObject(); + if (useIndexSetting == false) { + indexSpec.startObject("_source").field("mode", "synthetic").endObject(); + } indexSpec.startObject("properties").startObject("kwd").field("type", "keyword").endObject().endObject(); } indexSpec.endObject(); diff --git a/server/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java index e5b12f748543f..9d0dc9635537b 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java @@ -26,6 +26,7 @@ import org.elasticsearch.features.NodeFeature; import org.elasticsearch.index.IndexMode; import org.elasticsearch.index.IndexSettings; +import org.elasticsearch.index.IndexVersion; import org.elasticsearch.index.IndexVersions; import org.elasticsearch.index.query.QueryShardException; import org.elasticsearch.index.query.SearchExecutionContext; @@ -297,7 +298,7 @@ private static SourceFieldMapper resolveStaticInstance(final Mode sourceMode) { if (indexMode == IndexMode.STANDARD && settingSourceMode == Mode.STORED) { return DEFAULT; } - if (c.indexVersionCreated().onOrAfter(IndexVersions.DEPRECATE_SOURCE_MODE_MAPPER)) { + if (onOrAfterDeprecateModeVersion(c.indexVersionCreated())) { return resolveStaticInstance(settingSourceMode); } else { return new SourceFieldMapper(settingSourceMode, Explicit.IMPLICIT_TRUE, Strings.EMPTY_ARRAY, Strings.EMPTY_ARRAY, true); @@ -307,14 +308,14 @@ private static SourceFieldMapper resolveStaticInstance(final Mode sourceMode) { c.getIndexSettings().getMode(), c.getSettings(), c.indexVersionCreated().onOrAfter(IndexVersions.SOURCE_MAPPER_LOSSY_PARAMS_CHECK), - c.indexVersionCreated().before(IndexVersions.DEPRECATE_SOURCE_MODE_MAPPER) + onOrAfterDeprecateModeVersion(c.indexVersionCreated()) == false ) ) { @Override public MetadataFieldMapper.Builder parse(String name, Map node, MappingParserContext parserContext) throws MapperParsingException { assert name.equals(SourceFieldMapper.NAME) : name; - if (parserContext.indexVersionCreated().after(IndexVersions.DEPRECATE_SOURCE_MODE_MAPPER) && node.containsKey("mode")) { + if (onOrAfterDeprecateModeVersion(parserContext.indexVersionCreated()) && node.containsKey("mode")) { deprecationLogger.critical(DeprecationCategory.MAPPINGS, "mapping_source_mode", SourceFieldMapper.DEPRECATION_WARNING); } return super.parse(name, node, parserContext); @@ -481,4 +482,10 @@ public boolean isDisabled() { public boolean isStored() { return mode == null || mode == Mode.STORED; } + + public static boolean onOrAfterDeprecateModeVersion(IndexVersion version) { + return version.onOrAfter(IndexVersions.DEPRECATE_SOURCE_MODE_MAPPER); + // Adjust versions after backporting. + // || version.between(IndexVersions.BACKPORT_DEPRECATE_SOURCE_MODE_MAPPER, IndexVersions.UPGRADE_TO_LUCENE_10_0_0); + } } diff --git a/server/src/test/java/org/elasticsearch/index/mapper/DocumentParserContextTests.java b/server/src/test/java/org/elasticsearch/index/mapper/DocumentParserContextTests.java index be36ab9d6eac1..a4108caaf4fc3 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/DocumentParserContextTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/DocumentParserContextTests.java @@ -133,5 +133,6 @@ public void testCreateDynamicMapperBuilderContext() throws IOException { assertEquals(ObjectMapper.Defaults.DYNAMIC, resultFromParserContext.getDynamic()); assertEquals(MapperService.MergeReason.MAPPING_UPDATE, resultFromParserContext.getMergeReason()); assertFalse(resultFromParserContext.isInNestedContext()); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); } } diff --git a/server/src/test/java/org/elasticsearch/index/mapper/SourceFieldMapperTests.java b/server/src/test/java/org/elasticsearch/index/mapper/SourceFieldMapperTests.java index d7f33b9cdb3ba..fa173bc64518e 100644 --- a/server/src/test/java/org/elasticsearch/index/mapper/SourceFieldMapperTests.java +++ b/server/src/test/java/org/elasticsearch/index/mapper/SourceFieldMapperTests.java @@ -52,7 +52,8 @@ protected void registerParameters(ParameterChecker checker) throws IOException { checker.registerConflictCheck( "enabled", topMapping(b -> b.startObject(SourceFieldMapper.NAME).field("enabled", false).endObject()), - topMapping(b -> b.startObject(SourceFieldMapper.NAME).field("enabled", true).endObject()) + topMapping(b -> b.startObject(SourceFieldMapper.NAME).field("enabled", true).endObject()), + dm -> {} ); checker.registerUpdateCheck( topMapping(b -> b.startObject(SourceFieldMapper.NAME).field("enabled", true).endObject()), @@ -62,14 +63,18 @@ protected void registerParameters(ParameterChecker checker) throws IOException { checker.registerUpdateCheck( topMapping(b -> b.startObject(SourceFieldMapper.NAME).field("mode", "stored").endObject()), topMapping(b -> b.startObject(SourceFieldMapper.NAME).field("mode", "synthetic").endObject()), - dm -> assertTrue(dm.metadataMapper(SourceFieldMapper.class).isSynthetic()) + dm -> { + assertTrue(dm.metadataMapper(SourceFieldMapper.class).isSynthetic()); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); + } ); checker.registerConflictCheck("includes", b -> b.array("includes", "foo*")); checker.registerConflictCheck("excludes", b -> b.array("excludes", "foo*")); checker.registerConflictCheck( "mode", topMapping(b -> b.startObject(SourceFieldMapper.NAME).field("mode", "synthetic").endObject()), - topMapping(b -> b.startObject(SourceFieldMapper.NAME).field("mode", "stored").endObject()) + topMapping(b -> b.startObject(SourceFieldMapper.NAME).field("mode", "stored").endObject()), + dm -> assertWarnings(SourceFieldMapper.DEPRECATION_WARNING) ); } @@ -206,13 +211,14 @@ public void testSyntheticDisabledNotSupported() { ) ); assertThat(e.getMessage(), containsString("Cannot set both [mode] and [enabled] parameters")); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); } public void testSyntheticUpdates() throws Exception { MapperService mapperService = createMapperService(""" { "_doc" : { "_source" : { "mode" : "synthetic" } } } """); - + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); SourceFieldMapper mapper = mapperService.documentMapper().sourceMapper(); assertTrue(mapper.enabled()); assertTrue(mapper.isSynthetic()); @@ -220,6 +226,7 @@ public void testSyntheticUpdates() throws Exception { merge(mapperService, """ { "_doc" : { "_source" : { "mode" : "synthetic" } } } """); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); mapper = mapperService.documentMapper().sourceMapper(); assertTrue(mapper.enabled()); assertTrue(mapper.isSynthetic()); @@ -230,11 +237,15 @@ public void testSyntheticUpdates() throws Exception { Exception e = expectThrows(IllegalArgumentException.class, () -> merge(mapperService, """ { "_doc" : { "_source" : { "mode" : "stored" } } } """)); + assertThat(e.getMessage(), containsString("Cannot update parameter [mode] from [synthetic] to [stored]")); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); merge(mapperService, """ { "_doc" : { "_source" : { "mode" : "disabled" } } } """); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); + mapper = mapperService.documentMapper().sourceMapper(); assertFalse(mapper.enabled()); assertFalse(mapper.isSynthetic()); @@ -270,6 +281,7 @@ public void testSupportsNonDefaultParameterValues() throws IOException { topMapping(b -> b.startObject("_source").field("mode", randomBoolean() ? "synthetic" : "stored").endObject()) ).documentMapper().sourceMapper(); assertThat(sourceFieldMapper, notNullValue()); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); } Exception e = expectThrows( MapperParsingException.class, @@ -301,6 +313,8 @@ public void testSupportsNonDefaultParameterValues() throws IOException { .documentMapper() .sourceMapper() ); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); + assertThat(e.getMessage(), containsString("Parameter [mode=disabled] is not allowed in source")); e = expectThrows( @@ -409,6 +423,7 @@ public void testRecoverySourceWithSyntheticSource() throws IOException { ParsedDocument doc = docMapper.parse(source(b -> { b.field("field1", "value1"); })); assertNotNull(doc.rootDoc().getField("_recovery_source")); assertThat(doc.rootDoc().getField("_recovery_source").binaryValue(), equalTo(new BytesRef("{\"field1\":\"value1\"}"))); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); } { Settings settings = Settings.builder().put(INDICES_RECOVERY_SOURCE_ENABLED_SETTING.getKey(), false).build(); @@ -419,6 +434,7 @@ public void testRecoverySourceWithSyntheticSource() throws IOException { DocumentMapper docMapper = mapperService.documentMapper(); ParsedDocument doc = docMapper.parse(source(b -> b.field("field1", "value1"))); assertNull(doc.rootDoc().getField("_recovery_source")); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); } } @@ -613,6 +629,7 @@ public void testRecoverySourceWithLogsCustom() throws IOException { ParsedDocument doc = docMapper.parse(source(b -> { b.field("@timestamp", "2012-02-13"); })); assertNotNull(doc.rootDoc().getField("_recovery_source")); assertThat(doc.rootDoc().getField("_recovery_source").binaryValue(), equalTo(new BytesRef("{\"@timestamp\":\"2012-02-13\"}"))); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); } { Settings settings = Settings.builder() @@ -623,6 +640,7 @@ public void testRecoverySourceWithLogsCustom() throws IOException { DocumentMapper docMapper = mapperService.documentMapper(); ParsedDocument doc = docMapper.parse(source(b -> b.field("@timestamp", "2012-02-13"))); assertNull(doc.rootDoc().getField("_recovery_source")); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); } } @@ -691,6 +709,7 @@ public void testRecoverySourceWithTimeSeriesCustom() throws IOException { doc.rootDoc().getField("_recovery_source").binaryValue(), equalTo(new BytesRef("{\"@timestamp\":\"2012-02-13\",\"field\":\"value1\"}")) ); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); } { Settings settings = Settings.builder() @@ -704,6 +723,7 @@ public void testRecoverySourceWithTimeSeriesCustom() throws IOException { source("123", b -> b.field("@timestamp", "2012-02-13").field("field", randomAlphaOfLength(5)), null) ); assertNull(doc.rootDoc().getField("_recovery_source")); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); } } } diff --git a/server/src/test/java/org/elasticsearch/index/shard/ShardGetServiceTests.java b/server/src/test/java/org/elasticsearch/index/shard/ShardGetServiceTests.java index a49d895f38f67..307bc26c44ba6 100644 --- a/server/src/test/java/org/elasticsearch/index/shard/ShardGetServiceTests.java +++ b/server/src/test/java/org/elasticsearch/index/shard/ShardGetServiceTests.java @@ -21,6 +21,7 @@ import org.elasticsearch.index.engine.VersionConflictEngineException; import org.elasticsearch.index.get.GetResult; import org.elasticsearch.index.mapper.RoutingFieldMapper; +import org.elasticsearch.index.mapper.SourceFieldMapper; import org.elasticsearch.search.fetch.subphase.FetchSourceContext; import org.elasticsearch.xcontent.XContentType; @@ -114,6 +115,7 @@ public void testGetFromTranslogWithSyntheticSource() throws IOException { "mode": "synthetic" """; runGetFromTranslogWithOptions(docToIndex, sourceOptions, expectedFetchedSource, "\"long\"", 7L, true); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); } public void testGetFromTranslogWithDenseVector() throws IOException { diff --git a/test/framework/src/main/java/org/elasticsearch/index/mapper/MetadataMapperTestCase.java b/test/framework/src/main/java/org/elasticsearch/index/mapper/MetadataMapperTestCase.java index e86cb8562537f..449ecc099412f 100644 --- a/test/framework/src/main/java/org/elasticsearch/index/mapper/MetadataMapperTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/index/mapper/MetadataMapperTestCase.java @@ -38,7 +38,7 @@ protected boolean isSupportedOn(IndexVersion version) { protected abstract void registerParameters(ParameterChecker checker) throws IOException; - private record ConflictCheck(XContentBuilder init, XContentBuilder update) {} + private record ConflictCheck(XContentBuilder init, XContentBuilder update, Consumer check) {} private record UpdateCheck(XContentBuilder init, XContentBuilder update, Consumer check) {} @@ -58,7 +58,7 @@ public void registerConflictCheck(String param, CheckedConsumer {})); } /** @@ -68,8 +68,8 @@ public void registerConflictCheck(String param, CheckedConsumer check) { + conflictChecks.put(param, new ConflictCheck(init, update, check)); } public void registerUpdateCheck(XContentBuilder init, XContentBuilder update, Consumer check) { @@ -95,6 +95,7 @@ public final void testUpdates() throws IOException { e.getMessage(), anyOf(containsString("Cannot update parameter [" + param + "]"), containsString("different [" + param + "]")) ); + checker.conflictChecks.get(param).check.accept(mapperService.documentMapper()); } for (UpdateCheck updateCheck : checker.updateChecks) { MapperService mapperService = createMapperService(updateCheck.init); diff --git a/test/framework/src/main/java/org/elasticsearch/test/rest/ESRestTestCase.java b/test/framework/src/main/java/org/elasticsearch/test/rest/ESRestTestCase.java index 8ca9c0709b359..bdef0ba631b72 100644 --- a/test/framework/src/main/java/org/elasticsearch/test/rest/ESRestTestCase.java +++ b/test/framework/src/main/java/org/elasticsearch/test/rest/ESRestTestCase.java @@ -112,7 +112,6 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; -import java.util.Locale; import java.util.Map; import java.util.Objects; import java.util.Optional; @@ -1835,9 +1834,10 @@ public static CreateIndexResponse createIndex(RestClient client, String name, Se if (settings != null && settings.getAsBoolean(IndexSettings.INDEX_SOFT_DELETES_SETTING.getKey(), true) == false) { expectSoftDeletesWarning(request, name); - } else if (isSyntheticSourceConfiguredInMapping(mapping)) { - request.setOptions(expectVersionSpecificWarnings(v -> v.compatible(SourceFieldMapper.DEPRECATION_WARNING))); - } + } else if (isSyntheticSourceConfiguredInMapping(mapping) + && SourceFieldMapper.onOrAfterDeprecateModeVersion(minimumIndexVersion())) { + request.setOptions(expectVersionSpecificWarnings(v -> v.current(SourceFieldMapper.DEPRECATION_WARNING))); + } final Response response = client.performRequest(request); try (var parser = responseAsParser(response)) { return TestResponseParsers.parseCreateIndexResponse(parser); @@ -1898,8 +1898,30 @@ protected static boolean isSyntheticSourceConfiguredInMapping(String mapping) { if (sourceMapper == null) { return false; } - Object mode = sourceMapper.get("mode"); - return mode != null && mode.toString().toLowerCase(Locale.ROOT).equals("synthetic"); + return sourceMapper.get("mode") != null; + } + + @SuppressWarnings("unchecked") + protected static boolean isSyntheticSourceConfiguredInTemplate(String template) { + if (template == null) { + return false; + } + var values = XContentHelper.convertToMap(JsonXContent.jsonXContent, template, false); + for (Object value : values.values()) { + Map mappings = (Map) ((Map) value).get("mappings"); + if (mappings == null) { + continue; + } + Map sourceMapper = (Map) mappings.get(SourceFieldMapper.NAME); + if (sourceMapper == null) { + continue; + } + Object mode = sourceMapper.get("mode"); + if (mode != null) { + return true; + } + } + return false; } protected static Map getIndexSettings(String index) throws IOException { diff --git a/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/DeprecationChecks.java b/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/DeprecationChecks.java index d13f3cda2a82c..f9b2cc5afe3a5 100644 --- a/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/DeprecationChecks.java +++ b/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/DeprecationChecks.java @@ -96,7 +96,8 @@ private DeprecationChecks() {} IndexDeprecationChecks::checkIndexDataPath, IndexDeprecationChecks::storeTypeSettingCheck, IndexDeprecationChecks::frozenIndexSettingCheck, - IndexDeprecationChecks::deprecatedCamelCasePattern + IndexDeprecationChecks::deprecatedCamelCasePattern, + IndexDeprecationChecks::checkSourceModeInMapping ); static List> DATA_STREAM_CHECKS = List.of( diff --git a/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/IndexDeprecationChecks.java b/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/IndexDeprecationChecks.java index 8144d960df2e8..aaf58a44a6565 100644 --- a/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/IndexDeprecationChecks.java +++ b/x-pack/plugin/deprecation/src/main/java/org/elasticsearch/xpack/deprecation/IndexDeprecationChecks.java @@ -16,6 +16,7 @@ import org.elasticsearch.index.IndexVersion; import org.elasticsearch.index.IndexVersions; import org.elasticsearch.index.engine.frozen.FrozenEngine; +import org.elasticsearch.index.mapper.SourceFieldMapper; import org.elasticsearch.xpack.core.deprecation.DeprecationIssue; import java.util.ArrayList; @@ -201,6 +202,31 @@ static List findInPropertiesRecursively( return issues; } + static DeprecationIssue checkSourceModeInMapping(IndexMetadata indexMetadata, ClusterState clusterState) { + if (SourceFieldMapper.onOrAfterDeprecateModeVersion(indexMetadata.getCreationVersion())) { + boolean[] useSourceMode = { false }; + fieldLevelMappingIssue(indexMetadata, ((mappingMetadata, sourceAsMap) -> { + Object source = sourceAsMap.get("_source"); + if (source instanceof Map sourceMap) { + if (sourceMap.containsKey("mode")) { + useSourceMode[0] = true; + } + } + })); + if (useSourceMode[0]) { + return new DeprecationIssue( + DeprecationIssue.Level.CRITICAL, + SourceFieldMapper.DEPRECATION_WARNING, + "https://github.com/elastic/elasticsearch/pull/117172", + SourceFieldMapper.DEPRECATION_WARNING, + false, + null + ); + } + } + return null; + } + static DeprecationIssue deprecatedCamelCasePattern(IndexMetadata indexMetadata, ClusterState clusterState) { List fields = new ArrayList<>(); fieldLevelMappingIssue( diff --git a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/AsyncOperator.java b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/AsyncOperator.java index 2c36b42dee277..06b890603e489 100644 --- a/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/AsyncOperator.java +++ b/x-pack/plugin/esql/compute/src/main/java/org/elasticsearch/compute/operator/AsyncOperator.java @@ -43,6 +43,7 @@ public abstract class AsyncOperator implements Operator { private final int maxOutstandingRequests; private final LongAdder totalTimeInNanos = new LongAdder(); + private boolean finished = false; private volatile boolean closed = false; diff --git a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/LogsIndexModeCustomSettingsIT.java b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/LogsIndexModeCustomSettingsIT.java index f529b9fa1db96..99acbec04551e 100644 --- a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/LogsIndexModeCustomSettingsIT.java +++ b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/LogsIndexModeCustomSettingsIT.java @@ -7,9 +7,11 @@ package org.elasticsearch.xpack.logsdb; +import org.elasticsearch.client.Request; import org.elasticsearch.client.ResponseException; import org.elasticsearch.client.RestClient; import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.index.mapper.SourceFieldMapper; import org.elasticsearch.test.cluster.ElasticsearchCluster; import org.elasticsearch.test.cluster.local.distribution.DistributionType; import org.junit.Before; @@ -112,8 +114,11 @@ public void testConfigureStoredSourceBeforeIndexCreation() throws IOException { }"""; assertOK(putComponentTemplate(client, "logs@custom", storedSourceMapping)); - assertOK(createDataStream(client, "logs-custom-dev")); - + Request request = new Request("PUT", "_data_stream/logs-custom-dev"); + if (SourceFieldMapper.onOrAfterDeprecateModeVersion(minimumIndexVersion())) { + request.setOptions(expectVersionSpecificWarnings(v -> v.current(SourceFieldMapper.DEPRECATION_WARNING))); + } + assertOK(client.performRequest(request)); var mapping = getMapping(client, getDataStreamBackingIndex(client, "logs-custom-dev", 0)); String sourceMode = (String) subObject("_source").apply(mapping).get("mode"); assertThat(sourceMode, equalTo("stored")); @@ -182,7 +187,11 @@ public void testConfigureStoredSourceWhenIndexIsCreated() throws IOException { }"""; assertOK(putComponentTemplate(client, "logs@custom", storedSourceMapping)); - assertOK(createDataStream(client, "logs-custom-dev")); + Request request = new Request("PUT", "_data_stream/logs-custom-dev"); + if (SourceFieldMapper.onOrAfterDeprecateModeVersion(minimumIndexVersion())) { + request.setOptions(expectVersionSpecificWarnings(v -> v.current(SourceFieldMapper.DEPRECATION_WARNING))); + } + assertOK(client.performRequest(request)); var mapping = getMapping(client, getDataStreamBackingIndex(client, "logs-custom-dev", 0)); String sourceMode = (String) subObject("_source").apply(mapping).get("mode"); diff --git a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/LogsIndexModeRestTestIT.java b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/LogsIndexModeRestTestIT.java index cc7f5bdb33871..0990592cef5e3 100644 --- a/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/LogsIndexModeRestTestIT.java +++ b/x-pack/plugin/logsdb/src/javaRestTest/java/org/elasticsearch/xpack/logsdb/LogsIndexModeRestTestIT.java @@ -11,6 +11,7 @@ import org.elasticsearch.client.Response; import org.elasticsearch.client.ResponseException; import org.elasticsearch.client.RestClient; +import org.elasticsearch.index.mapper.SourceFieldMapper; import org.elasticsearch.test.rest.ESRestTestCase; import java.io.IOException; @@ -35,6 +36,11 @@ protected static Response putComponentTemplate(final RestClient client, final St throws IOException { final Request request = new Request("PUT", "/_component_template/" + componentTemplate); request.setJsonEntity(contends); + if (isSyntheticSourceConfiguredInTemplate(contends) && SourceFieldMapper.onOrAfterDeprecateModeVersion(minimumIndexVersion())) { + request.setOptions( + expectVersionSpecificWarnings((VersionSensitiveWarningsHandler v) -> v.current(SourceFieldMapper.DEPRECATION_WARNING)) + ); + } return client.performRequest(request); } diff --git a/x-pack/plugin/logsdb/src/test/java/org/elasticsearch/xpack/logsdb/SyntheticSourceIndexSettingsProviderTests.java b/x-pack/plugin/logsdb/src/test/java/org/elasticsearch/xpack/logsdb/SyntheticSourceIndexSettingsProviderTests.java index 1f5d26eaedf34..d6cdb9f761b31 100644 --- a/x-pack/plugin/logsdb/src/test/java/org/elasticsearch/xpack/logsdb/SyntheticSourceIndexSettingsProviderTests.java +++ b/x-pack/plugin/logsdb/src/test/java/org/elasticsearch/xpack/logsdb/SyntheticSourceIndexSettingsProviderTests.java @@ -81,10 +81,12 @@ public void testNewIndexHasSyntheticSourceUsage() throws IOException { boolean result = provider.newIndexHasSyntheticSourceUsage(indexName, null, settings, List.of(new CompressedXContent(mapping))); assertTrue(result); assertThat(newMapperServiceCounter.get(), equalTo(1)); + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); } { String mapping; - if (randomBoolean()) { + boolean withSourceMode = randomBoolean(); + if (withSourceMode) { mapping = """ { "_doc": { @@ -115,6 +117,9 @@ public void testNewIndexHasSyntheticSourceUsage() throws IOException { boolean result = provider.newIndexHasSyntheticSourceUsage(indexName, null, settings, List.of(new CompressedXContent(mapping))); assertFalse(result); assertThat(newMapperServiceCounter.get(), equalTo(2)); + if (withSourceMode) { + assertWarnings(SourceFieldMapper.DEPRECATION_WARNING); + } } } From 1402e6887ca45a74d2818725e254bd3062db05f8 Mon Sep 17 00:00:00 2001 From: Ioana Tagirta Date: Mon, 25 Nov 2024 19:29:22 +0100 Subject: [PATCH 27/34] Add support for aggregations, GROK and DISSECT for semantic_text (#117337) * Add support for aggregations for semantic_text * Add capability to csv tests for grok and dissect * Sort values to avoid flaky tests --- .../xpack/esql/qa/rest/EsqlSpecTestCase.java | 3 +- .../main/resources/mapping-semantic_text.json | 4 + .../src/main/resources/semantic_text.csv | 8 +- .../src/main/resources/semantic_text.csv-spec | 98 +++++++++++++++++-- .../xpack/esql/action/EsqlCapabilities.java | 7 +- .../function/aggregate/CountDistinct.java | 3 +- .../expression/function/aggregate/Max.java | 1 + .../expression/function/aggregate/Min.java | 3 +- .../expression/function/aggregate/Values.java | 1 + .../xpack/esql/planner/AggregateMapper.java | 9 +- .../aggregate/CountDistinctTests.java | 3 +- .../function/aggregate/CountTests.java | 3 +- .../function/aggregate/MaxTests.java | 3 +- .../function/aggregate/MinTests.java | 3 +- .../function/aggregate/TopTests.java | 3 +- .../function/aggregate/ValuesTests.java | 3 +- 16 files changed, 131 insertions(+), 24 deletions(-) diff --git a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java index 265d9f7bd8cd5..2484a428c4b03 100644 --- a/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java +++ b/x-pack/plugin/esql/qa/server/src/main/java/org/elasticsearch/xpack/esql/qa/rest/EsqlSpecTestCase.java @@ -172,7 +172,8 @@ public final void test() throws Throwable { } protected void shouldSkipTest(String testName) throws IOException { - if (testCase.requiredCapabilities.contains("semantic_text_type")) { + if (testCase.requiredCapabilities.contains("semantic_text_type") + || testCase.requiredCapabilities.contains("semantic_text_aggregations")) { assumeTrue("Inference test service needs to be supported for semantic_text", supportsInferenceTestService()); } checkCapabilities(adminClient(), testFeatureService, testName, testCase); diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/mapping-semantic_text.json b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/mapping-semantic_text.json index c587b69828170..db15133f036bb 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/mapping-semantic_text.json +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/mapping-semantic_text.json @@ -72,6 +72,10 @@ "st_base64": { "type": "semantic_text", "inference_id": "test_sparse_inference" + }, + "st_logs": { + "type": "semantic_text", + "inference_id": "test_sparse_inference" } } } diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/semantic_text.csv b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/semantic_text.csv index 6cae82cfefa0a..bd5fe7fad3a4e 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/semantic_text.csv +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/semantic_text.csv @@ -1,4 +1,4 @@ -_id:keyword,semantic_text_field:semantic_text,st_bool:semantic_text,st_cartesian_point:semantic_text,st_cartesian_shape:semantic_text,st_datetime:semantic_text,st_double:semantic_text,st_geopoint:semantic_text,st_geoshape:semantic_text,st_integer:semantic_text,st_ip:semantic_text,st_long:semantic_text,st_unsigned_long:semantic_text,st_version:semantic_text,st_multi_value:semantic_text,st_unicode:semantic_text,host:keyword,description:text,value:long,st_base64:semantic_text -1,live long and prosper,false,"POINT(4297.11 -1475.53)",,1953-09-02T00:00:00.000Z,5.20128E11,"POINT(42.97109630194 14.7552534413725)","POLYGON ((30 10\, 40 40\, 20 40\, 10 20\, 30 10))",23,1.1.1.1,2147483648,2147483648,1.2.3,["Hello there!", "This is a random value", "for testing purposes"],你吃饭了吗,"host1","some description1",1001,ZWxhc3RpYw== -2,all we have to decide is what to do with the time that is given to us,true,"POINT(7580.93 2272.77)",,2023-09-24T15:57:00.000Z,4541.11,"POINT(37.97109630194 21.7552534413725)","POLYGON ((30 10\, 40 40\, 20 40\, 10 20\, 30 10))",122,1.1.2.1,123,2147483648.2,9.0.0,["nice to meet you", "bye bye!"],["谢谢", "对不起我的中文不好"],"host2","some description2",1002,aGVsbG8= -3,be excellent to each other,,,,,,,,,,,,,,,"host3","some description3",1003, +_id:keyword,semantic_text_field:semantic_text,st_bool:semantic_text,st_cartesian_point:semantic_text,st_cartesian_shape:semantic_text,st_datetime:semantic_text,st_double:semantic_text,st_geopoint:semantic_text,st_geoshape:semantic_text,st_integer:semantic_text,st_ip:semantic_text,st_long:semantic_text,st_unsigned_long:semantic_text,st_version:semantic_text,st_multi_value:semantic_text,st_unicode:semantic_text,host:keyword,description:text,value:long,st_base64:semantic_text,st_logs:semantic_text +1,live long and prosper,false,"POINT(4297.11 -1475.53)",,1953-09-02T00:00:00.000Z,5.20128E11,"POINT(42.97109630194 14.7552534413725)","POLYGON ((30 10\, 40 40\, 20 40\, 10 20\, 30 10))",23,1.1.1.1,2147483648,2147483648,1.2.3,["Hello there!", "This is a random value", "for testing purposes"],你吃饭了吗,"host1","some description1",1001,ZWxhc3RpYw==,"2024-12-23T12:15:00.000Z 1.2.3.4 example@example.com 4553" +2,all we have to decide is what to do with the time that is given to us,true,"POINT(7580.93 2272.77)",,2023-09-24T15:57:00.000Z,4541.11,"POINT(37.97109630194 21.7552534413725)","POLYGON ((30 10\, 40 40\, 20 40\, 10 20\, 30 10))",122,1.1.2.1,123,2147483648.2,9.0.0,["nice to meet you", "bye bye!"],["谢谢", "对不起我的中文不好"],"host2","some description2",1002,aGVsbG8=,"2024-01-23T12:15:00.000Z 1.2.3.4 foo@example.com 42" +3,be excellent to each other,,,,,,,,,,,,,,,"host3","some description3",1003,,"2023-01-23T12:15:00.000Z 127.0.0.1 some.email@foo.com 42" diff --git a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/semantic_text.csv-spec b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/semantic_text.csv-spec index de2a79df06a50..43dc6e4d4acd2 100644 --- a/x-pack/plugin/esql/qa/testFixtures/src/main/resources/semantic_text.csv-spec +++ b/x-pack/plugin/esql/qa/testFixtures/src/main/resources/semantic_text.csv-spec @@ -88,19 +88,75 @@ _id:keyword | my_field:semantic_text 3 | be excellent to each other ; -simpleStats -required_capability: semantic_text_type +statsWithCount +required_capability: semantic_text_aggregations + +FROM semantic_text METADATA _id +| STATS result = COUNT(st_version) +; + +result:long +2 +; + +statsWithCountDistinct +required_capability: semantic_text_aggregations + +FROM semantic_text METADATA _id +| STATS result = COUNT_DISTINCT(st_version) +; + +result:long +2 +; + +statsWithValues +required_capability: semantic_text_aggregations + +FROM semantic_text METADATA _id +| STATS result = VALUES(st_version) +| EVAL result = MV_SORT(result) +; + +result:keyword +["1.2.3", "9.0.0"] +; + +statsWithMin +required_capability: semantic_text_aggregations + +FROM semantic_text METADATA _id +| STATS result = min(st_version) +; + +result:keyword +1.2.3 +; + +statsWithMax +required_capability: semantic_text_aggregations FROM semantic_text METADATA _id -| STATS COUNT(*) +| STATS result = max(st_version) ; -COUNT(*):long -3 +result:keyword +9.0.0 +; + +statsWithTop +required_capability: semantic_text_aggregations + +FROM semantic_text METADATA _id +| STATS result = top(st_version, 2, "asc") +; + +result:keyword +["1.2.3", "9.0.0"] ; statsWithGrouping -required_capability: semantic_text_type +required_capability: semantic_text_aggregations FROM semantic_text METADATA _id | STATS COUNT(*) BY st_version @@ -132,6 +188,36 @@ COUNT(*):long | my_field:semantic_text 1 | bye bye! ; +grok +required_capability: semantic_text_type + +FROM semantic_text METADATA _id +| GROK st_logs """%{TIMESTAMP_ISO8601:date} %{IP:ip} %{EMAILADDRESS:email} %{NUMBER:num}""" +| KEEP st_logs, date, ip, email, num +| SORT st_logs +; + +st_logs:semantic_text | date:keyword | ip:keyword | email:keyword | num:keyword +2023-01-23T12:15:00.000Z 127.0.0.1 some.email@foo.com 42 | 2023-01-23T12:15:00.000Z | 127.0.0.1 | some.email@foo.com | 42 +2024-01-23T12:15:00.000Z 1.2.3.4 foo@example.com 42 | 2024-01-23T12:15:00.000Z | 1.2.3.4 | foo@example.com | 42 +2024-12-23T12:15:00.000Z 1.2.3.4 example@example.com 4553 | 2024-12-23T12:15:00.000Z | 1.2.3.4 | example@example.com | 4553 +; + +dissect +required_capability: semantic_text_type + +FROM semantic_text METADATA _id +| DISSECT st_logs """%{date} %{ip} %{email} %{num}""" +| KEEP st_logs, date, ip, email, num +| SORT st_logs +; + +st_logs:semantic_text | date:keyword | ip:keyword | email:keyword | num:keyword +2023-01-23T12:15:00.000Z 127.0.0.1 some.email@foo.com 42 | 2023-01-23T12:15:00.000Z | 127.0.0.1 | some.email@foo.com | 42 +2024-01-23T12:15:00.000Z 1.2.3.4 foo@example.com 42 | 2024-01-23T12:15:00.000Z | 1.2.3.4 | foo@example.com | 42 +2024-12-23T12:15:00.000Z 1.2.3.4 example@example.com 4553 | 2024-12-23T12:15:00.000Z | 1.2.3.4 | example@example.com | 4553 +; + simpleWithLongValue required_capability: semantic_text_type diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java index d9ce7fca312b3..08fa7f0a9b213 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/action/EsqlCapabilities.java @@ -526,7 +526,12 @@ public enum Cap { /** * Fix for https://github.com/elastic/elasticsearch/issues/117054 */ - FIX_NESTED_FIELDS_NAME_CLASH_IN_INDEXRESOLVER; + FIX_NESTED_FIELDS_NAME_CLASH_IN_INDEXRESOLVER, + + /** + * support for aggregations on semantic_text + */ + SEMANTIC_TEXT_AGGREGATIONS(EsqlCorePlugin.SEMANTIC_TEXT_FEATURE_FLAG); private final boolean enabled; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountDistinct.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountDistinct.java index 5ae162f1fbb12..2e45b1c1fe082 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountDistinct.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountDistinct.java @@ -66,7 +66,8 @@ public class CountDistinct extends AggregateFunction implements OptionalArgument Map.entry(DataType.KEYWORD, CountDistinctBytesRefAggregatorFunctionSupplier::new), Map.entry(DataType.IP, CountDistinctBytesRefAggregatorFunctionSupplier::new), Map.entry(DataType.VERSION, CountDistinctBytesRefAggregatorFunctionSupplier::new), - Map.entry(DataType.TEXT, CountDistinctBytesRefAggregatorFunctionSupplier::new) + Map.entry(DataType.TEXT, CountDistinctBytesRefAggregatorFunctionSupplier::new), + Map.entry(DataType.SEMANTIC_TEXT, CountDistinctBytesRefAggregatorFunctionSupplier::new) ); private static final int DEFAULT_PRECISION = 3000; diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Max.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Max.java index 2165c3c7ad1a0..eb0c8abd1080b 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Max.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Max.java @@ -51,6 +51,7 @@ public class Max extends AggregateFunction implements ToAggregator, SurrogateExp Map.entry(DataType.IP, MaxIpAggregatorFunctionSupplier::new), Map.entry(DataType.KEYWORD, MaxBytesRefAggregatorFunctionSupplier::new), Map.entry(DataType.TEXT, MaxBytesRefAggregatorFunctionSupplier::new), + Map.entry(DataType.SEMANTIC_TEXT, MaxBytesRefAggregatorFunctionSupplier::new), Map.entry(DataType.VERSION, MaxBytesRefAggregatorFunctionSupplier::new) ); diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Min.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Min.java index 7d67868dd4134..472f0b1ff5cd1 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Min.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Min.java @@ -51,7 +51,8 @@ public class Min extends AggregateFunction implements ToAggregator, SurrogateExp Map.entry(DataType.IP, MinIpAggregatorFunctionSupplier::new), Map.entry(DataType.VERSION, MinBytesRefAggregatorFunctionSupplier::new), Map.entry(DataType.KEYWORD, MinBytesRefAggregatorFunctionSupplier::new), - Map.entry(DataType.TEXT, MinBytesRefAggregatorFunctionSupplier::new) + Map.entry(DataType.TEXT, MinBytesRefAggregatorFunctionSupplier::new), + Map.entry(DataType.SEMANTIC_TEXT, MinBytesRefAggregatorFunctionSupplier::new) ); @FunctionInfo( diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java index e7df990b20422..5260b3e8fa279 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/expression/function/aggregate/Values.java @@ -46,6 +46,7 @@ public class Values extends AggregateFunction implements ToAggregator { Map.entry(DataType.DOUBLE, ValuesDoubleAggregatorFunctionSupplier::new), Map.entry(DataType.KEYWORD, ValuesBytesRefAggregatorFunctionSupplier::new), Map.entry(DataType.TEXT, ValuesBytesRefAggregatorFunctionSupplier::new), + Map.entry(DataType.SEMANTIC_TEXT, ValuesBytesRefAggregatorFunctionSupplier::new), Map.entry(DataType.IP, ValuesBytesRefAggregatorFunctionSupplier::new), Map.entry(DataType.VERSION, ValuesBytesRefAggregatorFunctionSupplier::new), Map.entry(DataType.BOOLEAN, ValuesBooleanAggregatorFunctionSupplier::new) diff --git a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/AggregateMapper.java b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/AggregateMapper.java index 605e0d7c3109c..18bbfdf485a81 100644 --- a/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/AggregateMapper.java +++ b/x-pack/plugin/esql/src/main/java/org/elasticsearch/xpack/esql/planner/AggregateMapper.java @@ -302,12 +302,13 @@ private static String dataTypeToString(DataType type, Class aggClass) { case DataType.INTEGER, DataType.COUNTER_INTEGER -> "Int"; case DataType.LONG, DataType.DATETIME, DataType.COUNTER_LONG, DataType.DATE_NANOS -> "Long"; case DataType.DOUBLE, DataType.COUNTER_DOUBLE -> "Double"; - case DataType.KEYWORD, DataType.IP, DataType.VERSION, DataType.TEXT -> "BytesRef"; + case DataType.KEYWORD, DataType.IP, DataType.VERSION, DataType.TEXT, DataType.SEMANTIC_TEXT -> "BytesRef"; case GEO_POINT -> "GeoPoint"; case CARTESIAN_POINT -> "CartesianPoint"; - case SEMANTIC_TEXT, UNSUPPORTED, NULL, UNSIGNED_LONG, SHORT, BYTE, FLOAT, HALF_FLOAT, SCALED_FLOAT, OBJECT, SOURCE, DATE_PERIOD, - TIME_DURATION, CARTESIAN_SHAPE, GEO_SHAPE, DOC_DATA_TYPE, TSID_DATA_TYPE, PARTIAL_AGG -> - throw new EsqlIllegalArgumentException("illegal agg type: " + type.typeName()); + case UNSUPPORTED, NULL, UNSIGNED_LONG, SHORT, BYTE, FLOAT, HALF_FLOAT, SCALED_FLOAT, OBJECT, SOURCE, DATE_PERIOD, TIME_DURATION, + CARTESIAN_SHAPE, GEO_SHAPE, DOC_DATA_TYPE, TSID_DATA_TYPE, PARTIAL_AGG -> throw new EsqlIllegalArgumentException( + "illegal agg type: " + type.typeName() + ); }; } } diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountDistinctTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountDistinctTests.java index fff2d824fc710..e0b8c1356d087 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountDistinctTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountDistinctTests.java @@ -57,7 +57,8 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.ipCases(1, 1000), MultiRowTestCaseSupplier.versionCases(1, 1000), MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.KEYWORD), - MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.TEXT) + MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.TEXT), + MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.SEMANTIC_TEXT) ).flatMap(List::stream).forEach(fieldCaseSupplier -> { // With precision for (var precisionCaseSupplier : precisionSuppliers) { diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java index 979048534edbf..131072acff870 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/CountTests.java @@ -47,7 +47,8 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.geoPointCases(1, 1000, true), MultiRowTestCaseSupplier.cartesianPointCases(1, 1000, true), MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.KEYWORD), - MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.TEXT) + MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.TEXT), + MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.SEMANTIC_TEXT) ).flatMap(List::stream).map(CountTests::makeSupplier).collect(Collectors.toCollection(() -> suppliers)); // No rows diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MaxTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MaxTests.java index 7d4b46f2a902a..ae5b3691b0a7d 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MaxTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MaxTests.java @@ -48,7 +48,8 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.ipCases(1, 1000), MultiRowTestCaseSupplier.versionCases(1, 1000), MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.KEYWORD), - MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.TEXT) + MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.TEXT), + MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.SEMANTIC_TEXT) ).flatMap(List::stream).map(MaxTests::makeSupplier).collect(Collectors.toCollection(() -> suppliers)); suppliers.addAll( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MinTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MinTests.java index 58ef8d86017a8..ad2953f057635 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MinTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/MinTests.java @@ -48,7 +48,8 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.ipCases(1, 1000), MultiRowTestCaseSupplier.versionCases(1, 1000), MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.KEYWORD), - MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.TEXT) + MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.TEXT), + MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.SEMANTIC_TEXT) ).flatMap(List::stream).map(MinTests::makeSupplier).collect(Collectors.toCollection(() -> suppliers)); suppliers.addAll( diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/TopTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/TopTests.java index f7bf338caa099..f236e4d8faf98 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/TopTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/TopTests.java @@ -48,7 +48,8 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.booleanCases(1, 1000), MultiRowTestCaseSupplier.ipCases(1, 1000), MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.KEYWORD), - MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.TEXT) + MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.TEXT), + MultiRowTestCaseSupplier.stringCases(1, 1000, DataType.SEMANTIC_TEXT) ) .flatMap(List::stream) .map(fieldCaseSupplier -> TopTests.makeSupplier(fieldCaseSupplier, limitCaseSupplier, order)) diff --git a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesTests.java b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesTests.java index 29faceee7497e..5f35f8cada397 100644 --- a/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesTests.java +++ b/x-pack/plugin/esql/src/test/java/org/elasticsearch/xpack/esql/expression/function/aggregate/ValuesTests.java @@ -51,7 +51,8 @@ public static Iterable parameters() { MultiRowTestCaseSupplier.versionCases(1, 1000), // Lower values for strings, as they take more space and may trigger the circuit breaker MultiRowTestCaseSupplier.stringCases(1, 20, DataType.KEYWORD), - MultiRowTestCaseSupplier.stringCases(1, 20, DataType.TEXT) + MultiRowTestCaseSupplier.stringCases(1, 20, DataType.TEXT), + MultiRowTestCaseSupplier.stringCases(1, 20, DataType.SEMANTIC_TEXT) ).flatMap(List::stream).map(ValuesTests::makeSupplier).collect(Collectors.toCollection(() -> suppliers)); return parameterSuppliersFromTypedDataWithDefaultChecks( From 219372efaaf46a3b496df2142d3091d3434e67ec Mon Sep 17 00:00:00 2001 From: Brian Seeders Date: Mon, 25 Nov 2024 13:44:59 -0500 Subject: [PATCH 28/34] [CI] Ignore error about missing UBI artifact (#117506) --- .buildkite/scripts/dra-workflow.sh | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/.buildkite/scripts/dra-workflow.sh b/.buildkite/scripts/dra-workflow.sh index f2dc40ca1927f..bbfa81f51b286 100755 --- a/.buildkite/scripts/dra-workflow.sh +++ b/.buildkite/scripts/dra-workflow.sh @@ -75,6 +75,7 @@ find "$WORKSPACE" -type d -path "*/build/distributions" -exec chmod a+w {} \; echo --- Running release-manager +set +e # Artifacts should be generated docker run --rm \ --name release-manager \ @@ -91,4 +92,16 @@ docker run --rm \ --version "$ES_VERSION" \ --artifact-set main \ --dependency "beats:https://artifacts-${WORKFLOW}.elastic.co/beats/${BEATS_BUILD_ID}/manifest-${ES_VERSION}${VERSION_SUFFIX}.json" \ - --dependency "ml-cpp:https://artifacts-${WORKFLOW}.elastic.co/ml-cpp/${ML_CPP_BUILD_ID}/manifest-${ES_VERSION}${VERSION_SUFFIX}.json" + --dependency "ml-cpp:https://artifacts-${WORKFLOW}.elastic.co/ml-cpp/${ML_CPP_BUILD_ID}/manifest-${ES_VERSION}${VERSION_SUFFIX}.json" \ +2>&1 | tee release-manager.log +EXIT_CODE=$? +set -e + +# This failure is just generating a ton of noise right now, so let's just ignore it +# This should be removed once this issue has been fixed +if grep "elasticsearch-ubi-9.0.0-SNAPSHOT-docker-image.tar.gz" release-manager.log; then + echo "Ignoring error about missing ubi artifact" + exit 0 +fi + +exit "$EXIT_CODE" From 5a6464c552dc8d58dc40119292a99ff4d69cf385 Mon Sep 17 00:00:00 2001 From: Mikhail Berezovskiy Date: Mon, 25 Nov 2024 14:14:37 -0500 Subject: [PATCH 29/34] Add HTTP request info to leaking buffers (#116130) --- .../netty4/Netty4HttpServerTransport.java | 4 ++ .../netty4/Netty4LeakDetectionHandler.java | 40 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4LeakDetectionHandler.java diff --git a/modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4HttpServerTransport.java b/modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4HttpServerTransport.java index b971a52b7afb6..36c860f1fb90b 100644 --- a/modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4HttpServerTransport.java +++ b/modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4HttpServerTransport.java @@ -33,6 +33,7 @@ import io.netty.handler.timeout.ReadTimeoutException; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.util.AttributeKey; +import io.netty.util.ResourceLeakDetector; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -410,6 +411,9 @@ protected Result beginEncode(HttpResponse httpResponse, String acceptEncoding) t } }); } + if (ResourceLeakDetector.isEnabled()) { + ch.pipeline().addLast(new Netty4LeakDetectionHandler()); + } ch.pipeline() .addLast( "pipelining", diff --git a/modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4LeakDetectionHandler.java b/modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4LeakDetectionHandler.java new file mode 100644 index 0000000000000..8a0274872e493 --- /dev/null +++ b/modules/transport-netty4/src/main/java/org/elasticsearch/http/netty4/Netty4LeakDetectionHandler.java @@ -0,0 +1,40 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the "Elastic License + * 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side + * Public License v 1"; you may not use this file except in compliance with, at + * your election, the "Elastic License 2.0", the "GNU Affero General Public + * License v3.0 only", or the "Server Side Public License, v 1". + */ + +package org.elasticsearch.http.netty4; + +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelInboundHandlerAdapter; +import io.netty.handler.codec.http.HttpContent; +import io.netty.handler.codec.http.HttpRequest; + +import org.elasticsearch.tasks.Task; + +/** + * Inbound channel handler that enrich leaking buffers information from HTTP request. + * It helps to detect which handler is leaking buffers. Especially integration tests that run with + * paranoid leak detector that samples all buffers for leaking. Supplying informative opaque-id in + * integ test helps to narrow down problem (for example test name). + */ +public class Netty4LeakDetectionHandler extends ChannelInboundHandlerAdapter { + + private String info; + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) { + if (msg instanceof HttpRequest request) { + var opaqueId = request.headers().get(Task.X_OPAQUE_ID_HTTP_HEADER); + info = "method: " + request.method() + "; uri: " + request.uri() + "; x-opaque-id: " + opaqueId; + } + if (msg instanceof HttpContent content) { + content.touch(info); + } + ctx.fireChannelRead(msg); + } +} From 930a99cc3874e2e195f4a79a4c0f5953fcf27b45 Mon Sep 17 00:00:00 2001 From: Carlos Delgado <6339205+carlosdelest@users.noreply.github.com> Date: Mon, 25 Nov 2024 20:19:24 +0100 Subject: [PATCH 30/34] Fix and unmute synonyms tests using timeout (#117486) --- muted-tests.yml | 3 --- .../rest-api-spec/test/synonyms/10_synonyms_put.yml | 10 ++++++++-- .../test/synonyms/110_synonyms_invalid.yml | 5 ++++- .../rest-api-spec/test/synonyms/20_synonyms_get.yml | 5 ++++- .../rest-api-spec/test/synonyms/30_synonyms_delete.yml | 6 +++++- .../test/synonyms/40_synonyms_sets_get.yml | 5 ++++- .../test/synonyms/50_synonym_rule_put.yml | 6 +++++- .../test/synonyms/60_synonym_rule_get.yml | 6 ++++-- .../test/synonyms/70_synonym_rule_delete.yml | 5 ++++- .../test/synonyms/80_synonyms_from_index.yml | 5 ++++- .../test/synonyms/90_synonyms_reloading_for_synset.yml | 5 ++++- 11 files changed, 46 insertions(+), 15 deletions(-) diff --git a/muted-tests.yml b/muted-tests.yml index da8a093ebe674..f4c5a418666b9 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -185,9 +185,6 @@ tests: - class: org.elasticsearch.xpack.test.rest.XPackRestIT method: test {p0=snapshot/20_operator_privileges_disabled/Operator only settings can be set and restored by non-operator user when operator privileges is disabled} issue: https://github.com/elastic/elasticsearch/issues/116775 -- class: org.elasticsearch.backwards.MixedClusterClientYamlTestSuiteIT - method: test {p0=synonyms/90_synonyms_reloading_for_synset/Reload analyzers for specific synonym set} - issue: https://github.com/elastic/elasticsearch/issues/116777 - class: org.elasticsearch.xpack.searchablesnapshots.hdfs.SecureHdfsSearchableSnapshotsIT issue: https://github.com/elastic/elasticsearch/issues/116851 - class: org.elasticsearch.search.basic.SearchWithRandomIOExceptionsIT diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/10_synonyms_put.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/10_synonyms_put.yml index 675b98133ce11..93f1fafa7ab85 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/10_synonyms_put.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/10_synonyms_put.yml @@ -17,7 +17,10 @@ setup: - do: cluster.health: - wait_for_no_initializing_shards: true + index: .synonyms-2 + timeout: 2s + wait_for_status: green + ignore: 408 - do: synonyms.get_synonym: @@ -64,7 +67,10 @@ setup: - do: cluster.health: - wait_for_no_initializing_shards: true + index: .synonyms-2 + timeout: 2s + wait_for_status: green + ignore: 408 - do: synonyms.get_synonym: diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/110_synonyms_invalid.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/110_synonyms_invalid.yml index 4e77e10495109..7f545b466e65f 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/110_synonyms_invalid.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/110_synonyms_invalid.yml @@ -14,7 +14,10 @@ setup: # This is to ensure that all index shards (write and read) are available. In serverless this can take some time. - do: cluster.health: - wait_for_no_initializing_shards: true + index: .synonyms-2 + timeout: 2s + wait_for_status: green + ignore: 408 - do: indices.create: diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/20_synonyms_get.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/20_synonyms_get.yml index 5e6d4ec2341ad..9e6af0f471e6e 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/20_synonyms_get.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/20_synonyms_get.yml @@ -17,7 +17,10 @@ setup: # This is to ensure that all index shards (write and read) are available. In serverless this can take some time. - do: cluster.health: - wait_for_no_initializing_shards: true + index: .synonyms-2 + timeout: 2s + wait_for_status: green + ignore: 408 --- "Get synonyms set": diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/30_synonyms_delete.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/30_synonyms_delete.yml index 23c907f6a1137..62e8fe333ce99 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/30_synonyms_delete.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/30_synonyms_delete.yml @@ -15,7 +15,11 @@ setup: # This is to ensure that all index shards (write and read) are available. In serverless this can take some time. - do: cluster.health: - wait_for_no_initializing_shards: true + index: .synonyms-2 + timeout: 2s + wait_for_status: green + ignore: 408 + --- "Delete synonyms set": - do: diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/40_synonyms_sets_get.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/40_synonyms_sets_get.yml index 7c145dafd81cd..3815ea2c96c97 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/40_synonyms_sets_get.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/40_synonyms_sets_get.yml @@ -13,7 +13,10 @@ setup: # This is to ensure that all index shards (write and read) are available. In serverless this can take some time. - do: cluster.health: - wait_for_no_initializing_shards: true + index: .synonyms-2 + timeout: 2s + wait_for_status: green + ignore: 408 - do: synonyms.put_synonym: diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/50_synonym_rule_put.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/50_synonym_rule_put.yml index d8611000fe465..02757f711f690 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/50_synonym_rule_put.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/50_synonym_rule_put.yml @@ -17,7 +17,11 @@ setup: # This is to ensure that all index shards (write and read) are available. In serverless this can take some time. - do: cluster.health: - wait_for_no_initializing_shards: true + index: .synonyms-2 + timeout: 2s + wait_for_status: green + ignore: 408 + --- "Update a synonyms rule": - do: diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/60_synonym_rule_get.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/60_synonym_rule_get.yml index 0c962b51e08cb..9f1aa1d254169 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/60_synonym_rule_get.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/60_synonym_rule_get.yml @@ -17,8 +17,10 @@ setup: # This is to ensure that all index shards (write and read) are available. In serverless this can take some time. - do: cluster.health: - wait_for_no_initializing_shards: true - + index: .synonyms-2 + timeout: 2s + wait_for_status: green + ignore: 408 --- "Get a synonym rule": diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/70_synonym_rule_delete.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/70_synonym_rule_delete.yml index 41ab293158a35..d2c706decf4fd 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/70_synonym_rule_delete.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/70_synonym_rule_delete.yml @@ -17,7 +17,10 @@ setup: # This is to ensure that all index shards (write and read) are available. In serverless this can take some time. - do: cluster.health: - wait_for_no_initializing_shards: true + index: .synonyms-2 + timeout: 2s + wait_for_status: green + ignore: 408 --- "Delete synonym rule": diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/80_synonyms_from_index.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/80_synonyms_from_index.yml index 3aba0f0b4b78b..965cae551fab2 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/80_synonyms_from_index.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/80_synonyms_from_index.yml @@ -16,7 +16,10 @@ setup: # This is to ensure that all index shards (write and read) are available. In serverless this can take some time. - do: cluster.health: - wait_for_no_initializing_shards: true + index: .synonyms-2 + timeout: 2s + wait_for_status: green + ignore: 408 # Create an index with synonym_filter that uses that synonyms set - do: diff --git a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/90_synonyms_reloading_for_synset.yml b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/90_synonyms_reloading_for_synset.yml index ac01f2dc0178a..d6c98673253fb 100644 --- a/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/90_synonyms_reloading_for_synset.yml +++ b/rest-api-spec/src/yamlRestTest/resources/rest-api-spec/test/synonyms/90_synonyms_reloading_for_synset.yml @@ -28,7 +28,10 @@ # This is to ensure that all index shards (write and read) are available. In serverless this can take some time. - do: cluster.health: - wait_for_no_initializing_shards: true + index: .synonyms-2 + timeout: 2s + wait_for_status: green + ignore: 408 # Create my_index1 with synonym_filter that uses synonyms_set1 - do: From 565218e43e0874808d5929ccfecf7359d0423b37 Mon Sep 17 00:00:00 2001 From: elasticsearchmachine <58790826+elasticsearchmachine@users.noreply.github.com> Date: Tue, 26 Nov 2024 08:38:32 +1100 Subject: [PATCH 31/34] Mute org.elasticsearch.xpack.esql.qa.single_node.FieldExtractorIT testConstantKeywordField #117524 --- muted-tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/muted-tests.yml b/muted-tests.yml index f4c5a418666b9..2a800c2757f2b 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -232,6 +232,9 @@ tests: - class: org.elasticsearch.xpack.test.rest.XPackRestIT method: test {p0=transform/transforms_reset/Test reset running transform} issue: https://github.com/elastic/elasticsearch/issues/117473 +- class: org.elasticsearch.xpack.esql.qa.single_node.FieldExtractorIT + method: testConstantKeywordField + issue: https://github.com/elastic/elasticsearch/issues/117524 # Examples: # From 6260746cb958785c6d6c1aa023d4e00ee8b8d56f Mon Sep 17 00:00:00 2001 From: elasticsearchmachine <58790826+elasticsearchmachine@users.noreply.github.com> Date: Tue, 26 Nov 2024 08:39:00 +1100 Subject: [PATCH 32/34] Mute org.elasticsearch.xpack.esql.qa.multi_node.FieldExtractorIT testConstantKeywordField #117524 --- muted-tests.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/muted-tests.yml b/muted-tests.yml index 2a800c2757f2b..986bea5b248f1 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -235,6 +235,9 @@ tests: - class: org.elasticsearch.xpack.esql.qa.single_node.FieldExtractorIT method: testConstantKeywordField issue: https://github.com/elastic/elasticsearch/issues/117524 +- class: org.elasticsearch.xpack.esql.qa.multi_node.FieldExtractorIT + method: testConstantKeywordField + issue: https://github.com/elastic/elasticsearch/issues/117524 # Examples: # From e5b9b7e9babe42043184b4a2820645a46b9a000d Mon Sep 17 00:00:00 2001 From: elasticsearchmachine <58790826+elasticsearchmachine@users.noreply.github.com> Date: Tue, 26 Nov 2024 08:46:33 +1100 Subject: [PATCH 33/34] Mute org.elasticsearch.repositories.s3.RepositoryS3EcsClientYamlTestSuiteIT org.elasticsearch.repositories.s3.RepositoryS3EcsClientYamlTestSuiteIT #117525 --- muted-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/muted-tests.yml b/muted-tests.yml index 986bea5b248f1..37f36e9a19340 100644 --- a/muted-tests.yml +++ b/muted-tests.yml @@ -238,6 +238,8 @@ tests: - class: org.elasticsearch.xpack.esql.qa.multi_node.FieldExtractorIT method: testConstantKeywordField issue: https://github.com/elastic/elasticsearch/issues/117524 +- class: org.elasticsearch.repositories.s3.RepositoryS3EcsClientYamlTestSuiteIT + issue: https://github.com/elastic/elasticsearch/issues/117525 # Examples: # From 0f5eb0c2762938eac558eb1c09e9189ecd2f5113 Mon Sep 17 00:00:00 2001 From: Nhat Nguyen Date: Mon, 25 Nov 2024 15:15:14 -0800 Subject: [PATCH 34/34] Adjust deprecate index versions (#117523) Adjust the deprecation index check to support the backport version in 8.x. Relates #117183 --- .../src/main/java/org/elasticsearch/index/IndexVersions.java | 1 + .../org/elasticsearch/index/mapper/SourceFieldMapper.java | 5 ++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/main/java/org/elasticsearch/index/IndexVersions.java b/server/src/main/java/org/elasticsearch/index/IndexVersions.java index 7a5f469a57fa1..6344aa2a72ca9 100644 --- a/server/src/main/java/org/elasticsearch/index/IndexVersions.java +++ b/server/src/main/java/org/elasticsearch/index/IndexVersions.java @@ -131,6 +131,7 @@ private static Version parseUnchecked(String version) { public static final IndexVersion ADD_ROLE_MAPPING_CLEANUP_MIGRATION = def(8_518_00_0, Version.LUCENE_9_12_0); public static final IndexVersion LOGSDB_DEFAULT_IGNORE_DYNAMIC_BEYOND_LIMIT_BACKPORT = def(8_519_00_0, Version.LUCENE_9_12_0); public static final IndexVersion TIME_BASED_K_ORDERED_DOC_ID_BACKPORT = def(8_520_00_0, Version.LUCENE_9_12_0); + public static final IndexVersion V8_DEPRECATE_SOURCE_MODE_MAPPER = def(8_521_00_0, Version.LUCENE_9_12_0); public static final IndexVersion UPGRADE_TO_LUCENE_10_0_0 = def(9_000_00_0, Version.LUCENE_10_0_0); public static final IndexVersion LOGSDB_DEFAULT_IGNORE_DYNAMIC_BEYOND_LIMIT = def(9_001_00_0, Version.LUCENE_10_0_0); public static final IndexVersion TIME_BASED_K_ORDERED_DOC_ID = def(9_002_00_0, Version.LUCENE_10_0_0); diff --git a/server/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java b/server/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java index 9d0dc9635537b..e7c7ec3535b91 100644 --- a/server/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java +++ b/server/src/main/java/org/elasticsearch/index/mapper/SourceFieldMapper.java @@ -484,8 +484,7 @@ public boolean isStored() { } public static boolean onOrAfterDeprecateModeVersion(IndexVersion version) { - return version.onOrAfter(IndexVersions.DEPRECATE_SOURCE_MODE_MAPPER); - // Adjust versions after backporting. - // || version.between(IndexVersions.BACKPORT_DEPRECATE_SOURCE_MODE_MAPPER, IndexVersions.UPGRADE_TO_LUCENE_10_0_0); + return version.onOrAfter(IndexVersions.DEPRECATE_SOURCE_MODE_MAPPER) + || version.between(IndexVersions.V8_DEPRECATE_SOURCE_MODE_MAPPER, IndexVersions.UPGRADE_TO_LUCENE_10_0_0); } }

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 rw#|S*(tnD9!bT;hn3+St!FuvB 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