Skip to content

Commit 60a05a9

Browse files
authored
Revert "Remove V_8_0_0 transport version from tests (elastic#135942)" (elastic#136578)
This reverts commit 90ea9d3. elastic/elasticsearch-serverless#4688
1 parent d83584c commit 60a05a9

File tree

20 files changed

+1299
-16
lines changed

20 files changed

+1299
-16
lines changed
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.action.fieldcaps;
11+
12+
import org.elasticsearch.TransportVersion;
13+
import org.elasticsearch.TransportVersions;
14+
import org.elasticsearch.core.Predicates;
15+
16+
import java.util.HashMap;
17+
import java.util.Map;
18+
import java.util.Set;
19+
import java.util.function.Function;
20+
import java.util.function.Predicate;
21+
import java.util.stream.Collectors;
22+
23+
/**
24+
* Applies field type filters to field caps responses that come from earlier versions of ES
25+
* that do not support filtering directly.
26+
*/
27+
final class ResponseRewriter {
28+
29+
public static Map<String, IndexFieldCapabilities> rewriteOldResponses(
30+
TransportVersion version,
31+
Map<String, IndexFieldCapabilities> input,
32+
String[] filters,
33+
String[] allowedTypes
34+
) {
35+
if (version.onOrAfter(TransportVersions.V_8_2_0)) {
36+
return input; // nothing needs to be done
37+
}
38+
Function<IndexFieldCapabilities, IndexFieldCapabilities> transformer = buildTransformer(input, filters, allowedTypes);
39+
Map<String, IndexFieldCapabilities> rewritten = new HashMap<>();
40+
for (var entry : input.entrySet()) {
41+
IndexFieldCapabilities fc = transformer.apply(entry.getValue());
42+
if (fc != null) {
43+
rewritten.put(entry.getKey(), fc);
44+
}
45+
}
46+
return rewritten;
47+
}
48+
49+
private static Function<IndexFieldCapabilities, IndexFieldCapabilities> buildTransformer(
50+
Map<String, IndexFieldCapabilities> input,
51+
String[] filters,
52+
String[] allowedTypes
53+
) {
54+
Predicate<IndexFieldCapabilities> test = Predicates.always();
55+
Set<String> objects = null;
56+
Set<String> nestedObjects = null;
57+
if (allowedTypes.length > 0) {
58+
Set<String> at = Set.of(allowedTypes);
59+
test = test.and(ifc -> at.contains(ifc.type()));
60+
}
61+
for (String filter : filters) {
62+
if ("-parent".equals(filter)) {
63+
test = test.and(fc -> fc.type().equals("nested") == false && fc.type().equals("object") == false);
64+
}
65+
if ("-metadata".equals(filter)) {
66+
test = test.and(fc -> fc.isMetadatafield() == false);
67+
}
68+
if ("+metadata".equals(filter)) {
69+
test = test.and(IndexFieldCapabilities::isMetadatafield);
70+
}
71+
if ("-nested".equals(filter)) {
72+
if (nestedObjects == null) {
73+
nestedObjects = findTypes("nested", input);
74+
}
75+
Set<String> no = nestedObjects;
76+
test = test.and(fc -> isNestedField(fc.name(), no) == false);
77+
}
78+
if ("-multifield".equals(filter)) {
79+
// immediate parent is not an object field
80+
if (objects == null) {
81+
objects = findTypes("object", input);
82+
}
83+
Set<String> o = objects;
84+
test = test.and(fc -> isNotMultifield(fc.name(), o));
85+
}
86+
}
87+
Predicate<IndexFieldCapabilities> finalTest = test;
88+
return fc -> {
89+
if (finalTest.test(fc) == false) {
90+
return null;
91+
}
92+
return fc;
93+
};
94+
}
95+
96+
private static Set<String> findTypes(String type, Map<String, IndexFieldCapabilities> fieldCaps) {
97+
return fieldCaps.entrySet()
98+
.stream()
99+
.filter(entry -> type.equals(entry.getValue().type()))
100+
.map(Map.Entry::getKey)
101+
.collect(Collectors.toSet());
102+
}
103+
104+
private static boolean isNestedField(String field, Set<String> nestedParents) {
105+
for (String parent : nestedParents) {
106+
if (field.startsWith(parent + ".") || field.equals(parent)) {
107+
return true;
108+
}
109+
}
110+
return false;
111+
}
112+
113+
private static boolean isNotMultifield(String field, Set<String> objectFields) {
114+
int lastDotPos = field.lastIndexOf('.');
115+
if (lastDotPos == -1) {
116+
return true;
117+
}
118+
String parent = field.substring(0, lastDotPos);
119+
return objectFields.contains(parent);
120+
}
121+
122+
}

server/src/main/java/org/elasticsearch/action/fieldcaps/TransportFieldCapabilitiesAction.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ private static FieldCapabilitiesResponse merge(
440440
} else {
441441
subIndices = ArrayUtil.copyOfSubArray(indices, lastPendingIndex, i);
442442
}
443-
innerMerge(subIndices, fieldsBuilder, indexResponses[lastPendingIndex]);
443+
innerMerge(subIndices, fieldsBuilder, request, indexResponses[lastPendingIndex]);
444444
lastPendingIndex = i;
445445
}
446446
}
@@ -560,9 +560,15 @@ private static String nextIndex(Iterator<String> iter, Set<String> filtered) {
560560
private static void innerMerge(
561561
String[] indices,
562562
Map<String, Map<String, FieldCapabilities.Builder>> responseMapBuilder,
563+
FieldCapabilitiesRequest request,
563564
FieldCapabilitiesIndexResponse response
564565
) {
565-
Map<String, IndexFieldCapabilities> fields = response.get();
566+
Map<String, IndexFieldCapabilities> fields = ResponseRewriter.rewriteOldResponses(
567+
response.getOriginVersion(),
568+
response.get(),
569+
request.filters(),
570+
request.types()
571+
);
566572
for (Map.Entry<String, IndexFieldCapabilities> entry : fields.entrySet()) {
567573
final String field = entry.getKey();
568574
final IndexFieldCapabilities fieldCap = entry.getValue();

server/src/test/java/org/elasticsearch/action/admin/cluster/reroute/ClusterRerouteResponseTests.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99

1010
package org.elasticsearch.action.admin.cluster.reroute;
1111

12-
import org.elasticsearch.TransportVersion;
12+
import org.elasticsearch.TransportVersions;
1313
import org.elasticsearch.Version;
1414
import org.elasticsearch.cluster.ClusterName;
1515
import org.elasticsearch.cluster.ClusterState;
@@ -132,7 +132,7 @@ public void testToXContentWithDeprecatedClusterState() {
132132
"nodes_versions": [
133133
{
134134
"node_id": "node0",
135-
"transport_version": "%s",
135+
"transport_version": "8000099",
136136
"mappings_versions": {
137137
".system-index": {
138138
"version": 1,
@@ -218,7 +218,6 @@ public void testToXContentWithDeprecatedClusterState() {
218218
Version.CURRENT,
219219
IndexVersions.MINIMUM_COMPATIBLE,
220220
IndexVersion.current(),
221-
TransportVersion.current(),
222221
IndexVersion.current(),
223222
IndexVersion.current()
224223
),
@@ -334,7 +333,7 @@ private static ClusterState createClusterState() {
334333
.nodes(new DiscoveryNodes.Builder().add(node0).masterNodeId(node0.getId()).build())
335334
.putCompatibilityVersions(
336335
node0.getId(),
337-
TransportVersion.current(),
336+
TransportVersions.V_8_0_0,
338337
Map.of(".system-index", new SystemIndexDescriptor.MappingsVersion(1, 0))
339338
)
340339
.metadata(
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
package org.elasticsearch.action.fieldcaps;
11+
12+
import org.elasticsearch.TransportVersions;
13+
import org.elasticsearch.common.Strings;
14+
import org.elasticsearch.test.ESTestCase;
15+
16+
import java.util.Map;
17+
18+
public class ResponseRewriterTests extends ESTestCase {
19+
20+
public void testExcludeMetadata() {
21+
Map<String, IndexFieldCapabilities> oldResponse = Map.of(
22+
"field",
23+
fieldCaps("field", "keyword", false),
24+
"_index",
25+
fieldCaps("_index", "_index", true)
26+
);
27+
28+
Map<String, IndexFieldCapabilities> rewritten = ResponseRewriter.rewriteOldResponses(
29+
TransportVersions.V_8_0_0,
30+
oldResponse,
31+
new String[] { "-metadata" },
32+
Strings.EMPTY_ARRAY
33+
);
34+
35+
assertTrue(rewritten.containsKey("field"));
36+
assertFalse(rewritten.containsKey("_index"));
37+
}
38+
39+
public void testIncludeOnlyMetadata() {
40+
Map<String, IndexFieldCapabilities> oldResponse = Map.of(
41+
"field",
42+
fieldCaps("field", "keyword", false),
43+
"_index",
44+
fieldCaps("_index", "_index", true)
45+
);
46+
47+
Map<String, IndexFieldCapabilities> rewritten = ResponseRewriter.rewriteOldResponses(
48+
TransportVersions.V_8_0_0,
49+
oldResponse,
50+
new String[] { "+metadata" },
51+
Strings.EMPTY_ARRAY
52+
);
53+
54+
assertFalse(rewritten.containsKey("field"));
55+
assertTrue(rewritten.containsKey("_index"));
56+
}
57+
58+
public void testExcludeNested() {
59+
Map<String, IndexFieldCapabilities> oldResponse = Map.of(
60+
"field",
61+
fieldCaps("field", "keyword", false),
62+
"parent",
63+
fieldCaps("parent", "nested", false),
64+
"parent.child",
65+
fieldCaps("parent.child", "keyword", false)
66+
);
67+
68+
Map<String, IndexFieldCapabilities> rewritten = ResponseRewriter.rewriteOldResponses(
69+
TransportVersions.V_8_0_0,
70+
oldResponse,
71+
new String[] { "-nested" },
72+
Strings.EMPTY_ARRAY
73+
);
74+
75+
assertTrue(rewritten.containsKey("field"));
76+
assertFalse(rewritten.containsKey("parent.child"));
77+
assertFalse(rewritten.containsKey("parent"));
78+
}
79+
80+
public void testExcludeMultifield() {
81+
Map<String, IndexFieldCapabilities> oldResponse = Map.of(
82+
"field",
83+
fieldCaps("field", "text", false),
84+
"field.keyword",
85+
fieldCaps("field.keyword", "keyword", false),
86+
"parent",
87+
fieldCaps("parent", "object", false),
88+
"parent.child",
89+
fieldCaps("parent.child", "keyword", false)
90+
);
91+
92+
Map<String, IndexFieldCapabilities> rewritten = ResponseRewriter.rewriteOldResponses(
93+
TransportVersions.V_8_0_0,
94+
oldResponse,
95+
new String[] { "-multifield" },
96+
Strings.EMPTY_ARRAY
97+
);
98+
99+
assertTrue(rewritten.containsKey("field"));
100+
assertFalse(rewritten.containsKey("field.keyword"));
101+
assertTrue(rewritten.containsKey("parent.child"));
102+
}
103+
104+
public void testExcludeParents() {
105+
Map<String, IndexFieldCapabilities> oldResponse = Map.of(
106+
"field",
107+
fieldCaps("field", "text", false),
108+
"parent",
109+
fieldCaps("parent", "object", false),
110+
"parent.child",
111+
fieldCaps("parent.child", "keyword", false)
112+
);
113+
114+
Map<String, IndexFieldCapabilities> rewritten = ResponseRewriter.rewriteOldResponses(
115+
TransportVersions.V_8_0_0,
116+
oldResponse,
117+
new String[] { "-parent" },
118+
Strings.EMPTY_ARRAY
119+
);
120+
121+
assertTrue(rewritten.containsKey("field"));
122+
assertFalse(rewritten.containsKey("parent"));
123+
assertTrue(rewritten.containsKey("parent.child"));
124+
}
125+
126+
public void testAllowedTypes() {
127+
Map<String, IndexFieldCapabilities> oldResponse = Map.of(
128+
"text",
129+
fieldCaps("text", "text", false),
130+
"long",
131+
fieldCaps("long", "long", false),
132+
"keyword",
133+
fieldCaps("keyword", "keyword", false)
134+
);
135+
136+
Map<String, IndexFieldCapabilities> rewritten = ResponseRewriter.rewriteOldResponses(
137+
TransportVersions.V_8_0_0,
138+
oldResponse,
139+
Strings.EMPTY_ARRAY,
140+
new String[] { "text", "keyword" }
141+
);
142+
143+
assertTrue(rewritten.containsKey("text"));
144+
assertTrue(rewritten.containsKey("keyword"));
145+
assertFalse(rewritten.containsKey("long"));
146+
}
147+
148+
private static IndexFieldCapabilities fieldCaps(String name, String type, boolean isMetadata) {
149+
return new IndexFieldCapabilitiesBuilder(name, type).isMetadataField(isMetadata).build();
150+
}
151+
152+
}

server/src/test/java/org/elasticsearch/action/search/OpenPointInTimeRequestTests.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,19 @@
99

1010
package org.elasticsearch.action.search;
1111

12+
import org.elasticsearch.TransportVersion;
13+
import org.elasticsearch.TransportVersions;
14+
import org.elasticsearch.common.io.stream.BytesStreamOutput;
15+
import org.elasticsearch.common.io.stream.NamedWriteableAwareStreamInput;
16+
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
17+
import org.elasticsearch.common.io.stream.StreamInput;
1218
import org.elasticsearch.common.io.stream.Writeable;
1319
import org.elasticsearch.core.TimeValue;
1420
import org.elasticsearch.test.AbstractWireSerializingTestCase;
21+
import org.elasticsearch.test.TransportVersionUtils;
1522

1623
import java.io.IOException;
24+
import java.util.List;
1725

1826
import static org.hamcrest.Matchers.equalTo;
1927

@@ -87,4 +95,19 @@ protected OpenPointInTimeRequest mutateInstance(OpenPointInTimeRequest in) throw
8795
default -> throw new AssertionError("Unknown option");
8896
};
8997
}
98+
99+
public void testUseDefaultConcurrentForOldVersion() throws Exception {
100+
TransportVersion previousVersion = TransportVersionUtils.getPreviousVersion(TransportVersions.V_8_9_X);
101+
try (BytesStreamOutput output = new BytesStreamOutput()) {
102+
TransportVersion version = TransportVersionUtils.randomVersionBetween(random(), TransportVersions.V_8_0_0, previousVersion);
103+
output.setTransportVersion(version);
104+
OpenPointInTimeRequest original = createTestInstance();
105+
original.writeTo(output);
106+
try (StreamInput in = new NamedWriteableAwareStreamInput(output.bytes().streamInput(), new NamedWriteableRegistry(List.of()))) {
107+
in.setTransportVersion(version);
108+
OpenPointInTimeRequest copy = new OpenPointInTimeRequest(in);
109+
assertThat(copy.maxConcurrentShardRequests(), equalTo(5));
110+
}
111+
}
112+
}
90113
}

server/src/test/java/org/elasticsearch/common/settings/SettingsTests.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
import org.elasticsearch.ElasticsearchParseException;
1313
import org.elasticsearch.TransportVersion;
14+
import org.elasticsearch.TransportVersions;
1415
import org.elasticsearch.cluster.Diff;
1516
import org.elasticsearch.common.Strings;
1617
import org.elasticsearch.common.bytes.BytesReference;
@@ -619,7 +620,7 @@ public void testMissingValue() throws Exception {
619620

620621
public void testReadWriteArray() throws IOException {
621622
BytesStreamOutput output = new BytesStreamOutput();
622-
output.setTransportVersion(TransportVersion.current());
623+
output.setTransportVersion(randomFrom(TransportVersion.current(), TransportVersions.V_8_0_0));
623624
Settings settings = Settings.builder().putList("foo.bar", "0", "1", "2", "3").put("foo.bar.baz", "baz").build();
624625
settings.writeTo(output);
625626
StreamInput in = StreamInput.wrap(BytesReference.toBytes(output.bytes()));

0 commit comments

Comments
 (0)