-
Notifications
You must be signed in to change notification settings - Fork 25k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
REST high-level client: add simulate pipeline API #31158
Conversation
add to whitelist |
Pinging @elastic/es-core-infra |
* <a href="https://www.elastic.co/guide/en/elasticsearch/reference/master/simulate-pipeline-api.html"> | ||
* Simulate Pipeline API on elastic.co</a> | ||
*/ | ||
public SimulatePipelineResponse simulatePipeline(SimulatePipelineRequest request, Header... headers) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that the API has changed a bit and this is now deprecated. I will switch this to RequestOptions
once a review of the other stuff has been made.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's in, you can do so ;) can you also improve the javadocs adding the @param
etc. like in the other methods?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did a first review round and left some comments
* <a href="https://www.elastic.co/guide/en/elasticsearch/reference/master/simulate-pipeline-api.html"> | ||
* Simulate Pipeline API on elastic.co</a> | ||
*/ | ||
public SimulatePipelineResponse simulatePipeline(SimulatePipelineRequest request, Header... headers) throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
it's in, you can do so ;) can you also improve the javadocs adding the @param
etc. like in the other methods?
if (simulatePipelineRequest.getId() != null && !simulatePipelineRequest.getId().isEmpty()) { | ||
builder.addPathPart(simulatePipelineRequest.getId()); | ||
} | ||
builder.addPathPart("_simulate"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
addPathPartAsIs
); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that being this an integration test, we should randomize much less, if at all. We can have a fixed request and check that the response is expected, let's leave the randomizations for the unit tests.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you also the test the case where you get back an error?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shall we test the failure separately?
endpoint.add("_simulate"); | ||
assertEquals(endpoint.toString(), expectedRequest.getEndpoint()); | ||
assertEquals(HttpPost.METHOD_NAME, expectedRequest.getMethod()); | ||
assertEquals(expectedParams, expectedRequest.getParameters()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could you try it with a more realistic request body and assert on it at the end?
@@ -126,6 +128,16 @@ public void writeTo(StreamOutput out) throws IOException { | |||
} | |||
} | |||
|
|||
@Override | |||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException { | |||
if (source != null) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can the API even work when the source is null? maybe we should rather add this check to validate instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking at the constructor I don't think this will occur. Except if you create it with the blank instance constructor (which only happens in tests). I think we can remove this check if we ignore that constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
makes sense, the default constructor is there only for serialization, it will be used to create an instance and then call readFrom on it.
|
||
@Override | ||
protected boolean supportsUnknownFields() { | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment as above, let's return false here only if we can't insert random fields ever in any level of the object
|
||
@Override | ||
protected boolean assertToXContentEquivalence() { | ||
return false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this due to an exception?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Same reason as above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool, same comment as above :)
); | ||
} | ||
|
||
private boolean testSourceMapEquality(Map<String, Object> first, Map<String, Object> second) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we instead use ElasticsearchAssertions#assertToXContentEquivalent ?
|
||
@Override | ||
protected boolean supportsUnknownFields() { | ||
// Cannot support unknown fields because equality changes if new keys are added to _source |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good, that makes sense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
to clarify, this is because _source is mixed up with metadata right? if it was in a separate field, we would exclude it and we could return true here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do that I think. Since the metadata is separate. We would also need to ignore the _ingest
field.
@Override | ||
protected WriteableIngestDocument createTestInstance() { | ||
// We want to create a test instance without byte arrays. For testing byte arrays see testSourceFromXContentWithByteArray. | ||
// This is needed because for comparing byte[] Object.equal fails |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just an idea: could we maybe try to leave byte arrays but modify the equality assertion overriding assertEqualInstances ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know. equals
and hashCode
are already implemented for this so I did it like this. If you think it is better to override assertEqualInstances
I will make the change.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe give it a try and see if it gets better. I think it may, but I would have to try as well to see what it looks like :)
690e92a
to
da8fd19
Compare
} else if (expected instanceof byte[]) { | ||
//byte[] is really a special case for binary values when comparing SMILE and CBOR, arrays of other types | ||
//don't need to be handled. Ordinary arrays get parsed as lists. | ||
if (convertBase64Strings && actual instanceof String) { | ||
// for objects deserialized from XContent the content might be a Base64 encoded string | ||
actual = Base64.getDecoder().decode((String)actual); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@javanna I am not entirely sure if this is the best way to do this. The other option I can think of is to always serialize to XContent
and then assert equality. But then there doesn't seem to be any point to this as XContent
equality is already checked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed, I am not thrilled about this part. Can you remind me why we need this? What part of WriteableIngestDocument causes issues? Also confused because you didn't replace the existing assertions but you only added new ones. I wonder if this method is not testing things properly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the problem is there are byte arrays in the documents (_source
field). When you serialize it to XContent (if it is not CBOR
) it gets serialized to a base64 string. Now when you deserialize this its hard to check for equality for these two. Since I wanted to reuse code I decided to modify it here. You are also right kind of that this method has a bug. It checks for expected instanceof byte[]
and then casts actual
to byte[]
which can throw an exception. This is why I added the other assertion in the else clause. I think this is also true in the condition for List
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Before this change, I had separate tests for documents with byte arrays and without (similar to what we do with exceptions). Then you said maybe I should do assertEqualInstances
instead of separate tests. So that led to this ;)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok I see, what I don't follow is why we have this problem here and not in other places, as we have other API that can also hold _source in the same way. I will need to dig this up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I got it. Look at GetResponseTests, it holds the source but most of the problems (what makes the test a bit special) is the fields part rather than source. The trick is to generate the source using RandomObjects.randomSource which doesn't add byte arrays, much easier for testing xcontent stuff. RandomDocumentPicks#randomSource is used for a lot of the extensive ingest unit tests but outside of xcontent serialization. I think if you change that you will not need all these changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left a couple more comments, thanks @sohaibiftikhar ! I would not mind if also @nik9000 had a look ;)
@@ -93,31 +90,25 @@ public void testDeletePipeline() throws IOException { | |||
public void testSimulatePipeline() throws IOException { | |||
XContentType xContentType = randomFrom(XContentType.values()); | |||
XContentBuilder builder = XContentBuilder.builder(xContentType.xContent()); | |||
int numDocs = randomIntBetween(1, 10); | |||
boolean isVerbose = randomBoolean(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we also have two separate tests for with and without verbose rather than randomizing it?
); | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shall we test the failure separately?
boolean isVerbose = false; | ||
boolean isFirst = true; | ||
SimulateDocumentResult result = null; | ||
while (p.nextToken().equals(Token.FIELD_NAME)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I find this loop a bit weird, probably because I am used to a different way of parsing. In a lot of other places we rather do while ( (token = parser.nextToken()) != END_OBJECT)
. I find that one a bit easier to read as within the while you'd then have the different ifs for the different types of tokens and then you can also reason about naming. This way of parsing also requires us to add the nextToken in the default case, which looks a bit weird too. You would usually skipChildren on a start_array or start_object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. I will try to blend this piece with the other places ;)
(p, c) -> { | ||
ensureExpectedToken(Token.START_OBJECT, p.currentToken(), p::getTokenLocation); | ||
boolean isVerbose = false; | ||
boolean isFirst = true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe we can remove this variable as we only use it to assert on it? After all we are parsing our own responses and we can rely on the fact that you only get either verbose responses or ordinary ones, never both at the same time.
@@ -57,4 +54,53 @@ public void testSerialization() throws IOException { | |||
assertIngestDocument(otherSimulateDocumentBaseResult.getIngestDocument(), simulateDocumentBaseResult.getIngestDocument()); | |||
} | |||
} | |||
|
|||
protected SimulateDocumentBaseResult createTestInstance(boolean isFailure) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
static?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes thanks!
@@ -120,4 +93,104 @@ public void testSerialization() throws IOException { | |||
} | |||
} | |||
} | |||
|
|||
public static SimulatePipelineResponse createInstance(String pipelineId, boolean isVerbose, boolean withFailure) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wouldn't package protected be enough?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm.. probably. I will check this.
} else if (expected instanceof byte[]) { | ||
//byte[] is really a special case for binary values when comparing SMILE and CBOR, arrays of other types | ||
//don't need to be handled. Ordinary arrays get parsed as lists. | ||
if (convertBase64Strings && actual instanceof String) { | ||
// for objects deserialized from XContent the content might be a Base64 encoded string | ||
actual = Base64.getDecoder().decode((String)actual); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed, I am not thrilled about this part. Can you remind me why we need this? What part of WriteableIngestDocument causes issues? Also confused because you didn't replace the existing assertions but you only added new ones. I wonder if this method is not testing things properly.
Map<String, Object> source = IngestDocument.deepCopyMap(ingestDocument.getSourceAndMetadata()); | ||
metadataMap.keySet().forEach(mD -> source.remove(mD.getFieldName())); | ||
builder.field(SOURCE_FIELD, source); | ||
builder.field(INGEST_FIELD, ingestDocument.getIngestMetadata()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I like isolating this change to the parsing because it is big enough as it stands. But I think it'd be worth looking at IngestDocument
in a followup.
assertEquals(response.getResults().size(), parsedResponse.getResults().size()); | ||
for (int i=0; i < response.getResults().size(); i++) { | ||
if (response.isVerbose()) { | ||
assert response.getResults().get(i) instanceof SimulateDocumentVerboseResult; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tend to use assertThat(response.getResults().get(i), instanceOf(SimulateDocumentVerboseResult.class)
because it produces a nice error message. Not that it is all that important here because you can easily track down the error to the line and figure out what is up.
public void testFromXContentWithFailures() throws IOException { | ||
Supplier<SimulatePipelineResponse> instanceSupplier = SimulatePipelineResponseTests::createTestInstanceWithFailures; | ||
//exceptions are not of the same type whenever parsed back | ||
boolean assertToXContentEquivalence = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
bfcd543
to
d72bb03
Compare
-- removed changed to RandomDocumentPicks
-- Started using RandomObjects instead of RandomDocumentPicks -- Removed changes to ElasticsearchAssertions
d72bb03
to
d08dcb5
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left some more comments, mostly minors, LGTM otherwise
public void testSimulatePipeline() throws IOException { | ||
XContentType xContentType = randomFrom(XContentType.values()); | ||
XContentBuilder builder = XContentBuilder.builder(xContentType.xContent()); | ||
boolean isVerbose = randomBoolean(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I have left a comment on this before, can we avoid randomizing values in integration tests and rather have two tests, one for verbose and one without verbose? Same for failures
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That means four tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yep
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. I am sorry I missed this comment from before. I separated it now.
@Override | ||
protected boolean assertToXContentEquivalence() { | ||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe we can remove this and supportsUnknownFields given that we are now using the default values?
|
||
public class SimulateDocumentBaseResultTests extends AbstractXContentTestCase<SimulateDocumentBaseResult> { | ||
|
||
public void testSerialization() throws IOException { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: I wonder if transport serialization should be tested separately, in a test class that extends from AbstractStreamableTestCase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see that you didn't add this but only moved it, then I don't mean to make this PR too big, you can leave this as-is
@Override | ||
protected boolean assertToXContentEquivalence() { | ||
return true; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here too , remove the methods that are no longer needed?
|
||
@Override | ||
protected Predicate<String> getRandomFieldsExcludeFilter() { | ||
// We cannot have random fields in the _source field and _ingest field |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is it worth sharing this predicate somewhere given that it's the same in all these tests?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was thinking the same. What would you suggest?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The same also goes for testFromXContentWithFailures
. Probably should extend AbstractXContentTestCase
with AbstractXContentWithFailureTests
and add this method and createTestInstanceWithFailures
. Then extend it everywhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would keep it simple, add a static method somewhere and call it where it's needed. On extending AbstractXContentTestCase and adding another base test class, I am not too sure, just because we have already a lot of test base classes and it's hard for folks to figure out which one is right for them. Maybe it's a good idea though, if you want to go that route I am not against it, I think :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay. But its not the same everywhere. At two places it is field.startsWith
and the other two is field.contains
. I can make everything contains and it would still work I guess. But startsWith
is more accurate in some cases.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok, I thought that they were all the same, let's not complicate it then, I am fine with leaving as-is
result = new SimulateDocumentVerboseResult(results); | ||
break; | ||
case WriteableIngestDocument.DOC_FIELD: | ||
case "error": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe have two cases for this rather than a single case with an if that checks again?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, this made more sense before when it was a bit different. I will change this.
ensureExpectedToken(parser.currentToken(), Token.FIELD_NAME, parser::getTokenLocation); | ||
String fieldName = parser.currentName(); | ||
parser.nextToken(); | ||
switch(fieldName) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would find this even more accurate if we looked at the token type upfront rather than checking first the field name and then asserting on the token type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But they are different for different cases?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the subtle difference is that if something with same name but wrong type comes up, now it's rejected, while checking first the token type it would be ignored. It also makes parsing code more readable because you know exactly for which type of section you do what. At least that's what I got used to.
-- Added separate tests for failure and verbose responses instead of randomization -- Changed parsing for SimulatePipelineResponse
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
left two super small nits. thanks @sohaibiftikhar !
token = parser.nextToken(); | ||
if (token == Token.START_ARRAY) { | ||
switch (fieldName) { | ||
case SimulateDocumentVerboseResult.PROCESSOR_RESULT_FIELD: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you do else if here please?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You mean something like:
if ( fieldName.equals(PROCESSOR_RESULT_FIELD)) { /* do something */ }
else { /* skip children */ }
I wanted to make it similar to the one below so I did a switch statement. But I agree it would make more sense with an if.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes that is what I meant, thank you!
switch (fieldName) { | ||
case SimulateDocumentVerboseResult.PROCESSOR_RESULT_FIELD: | ||
List<SimulateProcessorResult> results = new ArrayList<>(); | ||
while ((token = parser.nextToken()).equals(Token.START_OBJECT)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use == ?
retest this please |
@sohaibiftikhar would you mind merging master in? Hopefully that will fix the test failures. |
…o simulate_pipeline
…o simulate_pipeline
thanks @sohaibiftikhar ! |
* master: Add get field mappings to High Level REST API Client (#31423) [DOCS] Updates Watcher examples for code testing (#31152) TEST: Add bwc recovery tests with synced-flush index [DOCS] Move sql to docs (#31474) [DOCS] Move monitoring to docs folder (#31477) Core: Combine doExecute methods in TransportAction (#31517) IndexShard should not return null stats (#31528) fix repository update with the same settings but different type (#31458) Fix Mockito trying to mock IOException that isn't thrown by method (#31433) (#31527) Node selector per client rather than per request (#31471) Core: Combine messageRecieved methods in TransportRequestHandler (#31519) Upgrade to Lucene 7.4.0. (#31529) [ML] Add ML filter update API (#31437) Allow multiple unicast host providers (#31509) Avoid deprecation warning when running the ML datafeed extractor. (#31463) REST high-level client: add simulate pipeline API (#31158) Get Mapping API to honour allow_no_indices and ignore_unavailable (#31507) [PkiRealm] Invalidate cache on role mappings change (#31510) [Security] Check auth scheme case insensitively (#31490) In NumberFieldType equals and hashCode, make sure that NumberType is taken into account. (#31514) [DOCS] Fix REST tests in SQL docs [DOCS] Add code snippet testing in more ML APIs (#31339) Core: Remove ThreadPool from base TransportAction (#31492) [DOCS] Remove fixed file from build.gradle Rename createNewTranslog to fileBasedRecovery (#31508) Test: Skip assertion on windows [DOCS] Creates field and document level security overview (#30937) [DOCS] Significantly improve SQL docs [DOCS] Move migration APIs to docs (#31473) Core: Convert TransportAction.execute uses to client calls (#31487) Return transport addresses from UnicastHostsProvider (#31426) Ensure local addresses aren't null (#31440) Remove unused generic type for client execute method (#31444) Introduce http and tcp server channels (#31446)
* 6.x: Fix broken backport of #31578 by adjusting constructor (#31587) ingest: Add ignore_missing property to foreach filter (#22147) (#31578) Add package pre-install check for java binary (#31343) Docs: Clarify sensitive fields watcher encryption (#31551) Watcher: Remove never executed code (#31135) Improve test times for tests using `RandomObjects::addFields` (#31556) Revert "Remove RestGetAllAliasesAction (#31308)" REST high-level client: add simulate pipeline API (#31158) Get Mapping API to honour allow_no_indices and ignore_unavailable (#31507) Fix Mockito trying to mock IOException that isn't thrown by method (#31433) (#31527) [Test] Add full cluster restart test for Rollup (#31533) Enhance thread context uniqueness assertion fix writeIndex evaluation for aliases (#31562) Add x-opaque-id to search slow logs (#31539) Watcher: Fix put watch action (#31524) [DOCS] Significantly improve SQL docs turn GetFieldMappingsResponse to ToXContentObject (#31544) TEST: Unmute testHistoryUUIDIsGenerated Ingest Attachment: Upgrade Tika to 1.18 (#31252) TEST: Correct the assertion arguments order (#31540)
relates to #27205