Skip to content

Commit e321fb0

Browse files
Fix template equals when mappings are wrapped (#77008)
When create template v2. mappings will add _doc. This will cause the created template to be inconsistent with the queried template. In template class, add mappingsEquals method, to deal with this case. reproduced: MetadataIndexTemplateServiceTests.testAddComponentTemplate when mappings are not null, the case will failed. ``` Template template = new Template( Settings.builder().build(), new CompressedXContent("{\"properties\":{\"@timestamp\":{\"type\":\"date\"}}}"), ComponentTemplateTests.randomAliases() ); ComponentTemplate componentTemplate = new ComponentTemplate(template, 1L, new HashMap<>()); ``` Co-authored-by: Elastic Machine <[email protected]>
1 parent 096b8cc commit e321fb0

File tree

3 files changed

+87
-55
lines changed

3 files changed

+87
-55
lines changed

server/src/main/java/org/elasticsearch/cluster/metadata/Template.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
package org.elasticsearch.cluster.metadata;
1010

1111
import org.elasticsearch.cluster.AbstractDiffable;
12+
import org.elasticsearch.common.util.Maps;
1213
import org.elasticsearch.core.Nullable;
1314
import org.elasticsearch.common.xcontent.ParseField;
1415
import org.elasticsearch.common.Strings;
@@ -141,7 +142,7 @@ public boolean equals(Object obj) {
141142
}
142143
Template other = (Template) obj;
143144
return Objects.equals(settings, other.settings) &&
144-
Objects.equals(mappings, other.mappings) &&
145+
mappingsEquals(this.mappings, other.mappings) &&
145146
Objects.equals(aliases, other.aliases);
146147
}
147148

@@ -178,11 +179,33 @@ public XContentBuilder toXContent(XContentBuilder builder, Params params) throws
178179
}
179180

180181
@SuppressWarnings("unchecked")
181-
private static Map<String, Object> reduceMapping(Map<String, Object> mapping) {
182+
static Map<String, Object> reduceMapping(Map<String, Object> mapping) {
182183
if (mapping.size() == 1 && MapperService.SINGLE_MAPPING_NAME.equals(mapping.keySet().iterator().next())) {
183184
return (Map<String, Object>) mapping.values().iterator().next();
184185
} else {
185186
return mapping;
186187
}
187188
}
189+
190+
static boolean mappingsEquals(CompressedXContent m1, CompressedXContent m2) {
191+
if (m1 == m2) {
192+
return true;
193+
}
194+
195+
if (m1 == null || m2 == null) {
196+
return false;
197+
}
198+
199+
if (m1.equals(m2)) {
200+
return true;
201+
}
202+
203+
Map<String, Object> thisUncompressedMapping = reduceMapping(
204+
XContentHelper.convertToMap(m1.uncompressed(), true, XContentType.JSON).v2()
205+
);
206+
Map<String, Object> otherUncompressedMapping = reduceMapping(
207+
XContentHelper.convertToMap(m2.uncompressed(), true, XContentType.JSON).v2()
208+
);
209+
return Maps.deepEquals(thisUncompressedMapping, otherUncompressedMapping);
210+
}
188211
}

server/src/test/java/org/elasticsearch/cluster/metadata/ComponentTemplateTests.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,25 @@
99
package org.elasticsearch.cluster.metadata;
1010

1111
import org.elasticsearch.cluster.Diff;
12+
import org.elasticsearch.common.Strings;
13+
import org.elasticsearch.common.bytes.BytesArray;
1214
import org.elasticsearch.common.compress.CompressedXContent;
1315
import org.elasticsearch.common.io.stream.Writeable;
1416
import org.elasticsearch.common.settings.Settings;
17+
import org.elasticsearch.common.xcontent.XContentFactory;
18+
import org.elasticsearch.common.xcontent.XContentHelper;
1519
import org.elasticsearch.common.xcontent.XContentParser;
20+
import org.elasticsearch.common.xcontent.XContentType;
21+
import org.elasticsearch.index.mapper.MapperService;
1622
import org.elasticsearch.test.AbstractDiffableSerializationTestCase;
1723
import org.elasticsearch.test.ESTestCase;
1824

1925
import java.io.IOException;
2026
import java.util.Collections;
2127
import java.util.Map;
2228

29+
import static org.hamcrest.Matchers.equalTo;
30+
2331
public class ComponentTemplateTests extends AbstractDiffableSerializationTestCase<ComponentTemplate> {
2432
@Override
2533
protected ComponentTemplate makeTestChanges(ComponentTemplate testInstance) {
@@ -154,4 +162,52 @@ public static ComponentTemplate mutateTemplate(ComponentTemplate orig) {
154162
throw new IllegalStateException("illegal randomization branch");
155163
}
156164
}
165+
166+
public void testMappingsEquals() throws IOException {
167+
{
168+
CompressedXContent mappings = randomMappings();
169+
assertThat(Template.mappingsEquals(mappings, mappings), equalTo(true));
170+
}
171+
172+
{
173+
assertThat(Template.mappingsEquals(null, null), equalTo(true));
174+
}
175+
176+
{
177+
CompressedXContent mappings = randomMappings();
178+
assertThat(Template.mappingsEquals(mappings, null), equalTo(false));
179+
assertThat(Template.mappingsEquals(null, mappings), equalTo(false));
180+
}
181+
182+
{
183+
String randomString = randomAlphaOfLength(10);
184+
CompressedXContent m1 = new CompressedXContent("{\"properties\":{\"" + randomString + "\":{\"type\":\"keyword\"}}}");
185+
CompressedXContent m2 = new CompressedXContent("{\"properties\":{\"" + randomString + "\":{\"type\":\"keyword\"}}}");
186+
assertThat(Template.mappingsEquals(m1, m2), equalTo(true));
187+
}
188+
189+
{
190+
CompressedXContent m1 = randomMappings();
191+
CompressedXContent m2 = new CompressedXContent("{\"properties\":{\"" + randomAlphaOfLength(10) + "\":{\"type\":\"keyword\"}}}");
192+
assertThat(Template.mappingsEquals(m1, m2), equalTo(false));
193+
}
194+
195+
{
196+
Map<String, Object> map = XContentHelper.convertToMap(
197+
new BytesArray(
198+
"{\""
199+
+ MapperService.SINGLE_MAPPING_NAME
200+
+ "\":{\"properties\":{\""
201+
+ randomAlphaOfLength(10)
202+
+ "\":{\"type\":\"keyword\"}}}}"
203+
),
204+
true,
205+
XContentType.JSON
206+
).v2();
207+
Map<String, Object> reduceMap = Template.reduceMapping(map);
208+
CompressedXContent m1 = new CompressedXContent(Strings.toString(XContentFactory.jsonBuilder().map(map)));
209+
CompressedXContent m2 = new CompressedXContent(Strings.toString(XContentFactory.jsonBuilder().map(reduceMap)));
210+
assertThat(Template.mappingsEquals(m1, m2), equalTo(true));
211+
}
212+
}
157213
}

server/src/test/java/org/elasticsearch/cluster/metadata/MetadataIndexTemplateServiceTests.java

Lines changed: 6 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,8 @@
2323
import org.elasticsearch.common.settings.IndexScopedSettings;
2424
import org.elasticsearch.common.settings.Settings;
2525
import org.elasticsearch.core.TimeValue;
26-
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
2726
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
2827
import org.elasticsearch.common.xcontent.XContentFactory;
29-
import org.elasticsearch.common.xcontent.XContentParser;
30-
import org.elasticsearch.common.xcontent.XContentType;
3128
import org.elasticsearch.env.Environment;
3229
import org.elasticsearch.index.Index;
3330
import org.elasticsearch.index.mapper.DataStreamTimestampFieldMapper;
@@ -42,7 +39,6 @@
4239
import org.elasticsearch.plugins.Plugin;
4340
import org.elasticsearch.test.ESSingleNodeTestCase;
4441

45-
import java.io.IOException;
4642
import java.util.ArrayList;
4743
import java.util.Arrays;
4844
import java.util.Collection;
@@ -341,7 +337,11 @@ public void testPutGlobalTemplateWithIndexHiddenSetting() throws Exception {
341337
public void testAddComponentTemplate() throws Exception{
342338
MetadataIndexTemplateService metadataIndexTemplateService = getMetadataIndexTemplateService();
343339
ClusterState state = ClusterState.EMPTY_STATE;
344-
Template template = new Template(Settings.builder().build(), null, ComponentTemplateTests.randomAliases());
340+
Template template = new Template(
341+
Settings.builder().build(),
342+
new CompressedXContent("{\"properties\":{\"@timestamp\":{\"type\":\"date\"}}}"),
343+
ComponentTemplateTests.randomAliases()
344+
);
345345
ComponentTemplate componentTemplate = new ComponentTemplate(template, 1L, new HashMap<>());
346346
state = metadataIndexTemplateService.addComponentTemplate(state, false, "foo", componentTemplate);
347347

@@ -1587,55 +1587,8 @@ clusterService, createIndexService, new AliasValidator(), indicesService,
15871587
new IndexScopedSettings(Settings.EMPTY, IndexScopedSettings.BUILT_IN_INDEX_SETTINGS), xContentRegistry());
15881588
}
15891589

1590-
@SuppressWarnings("unchecked")
15911590
public static void assertTemplatesEqual(ComposableIndexTemplate actual, ComposableIndexTemplate expected) {
1592-
ComposableIndexTemplate actualNoTemplate = new ComposableIndexTemplate(actual.indexPatterns(), null,
1593-
actual.composedOf(), actual.priority(), actual.version(), actual.metadata(), actual.getDataStreamTemplate(), null);
1594-
ComposableIndexTemplate expectedNoTemplate = new ComposableIndexTemplate(expected.indexPatterns(), null,
1595-
expected.composedOf(), expected.priority(), expected.version(), expected.metadata(), expected.getDataStreamTemplate(), null);
1596-
1597-
assertThat(actualNoTemplate, equalTo(expectedNoTemplate));
1598-
Template actualTemplate = actual.template();
1599-
Template expectedTemplate = expected.template();
1600-
1601-
assertThat("expected both templates to have either a template or no template",
1602-
Objects.nonNull(actualTemplate), equalTo(Objects.nonNull(expectedTemplate)));
1603-
1604-
if (actualTemplate != null) {
1605-
assertThat(actualTemplate.settings(), equalTo(expectedTemplate.settings()));
1606-
assertThat(actualTemplate.aliases(), equalTo(expectedTemplate.aliases()));
1607-
assertThat("expected both templates to have either mappings or no mappings",
1608-
Objects.nonNull(actualTemplate.mappings()), equalTo(Objects.nonNull(expectedTemplate.mappings())));
1609-
1610-
if (actualTemplate.mappings() != null) {
1611-
Map<String, Object> actualMappings;
1612-
Map<String, Object> expectedMappings;
1613-
try (XContentParser parser = XContentType.JSON.xContent()
1614-
.createParser(new NamedXContentRegistry(List.of()), LoggingDeprecationHandler.INSTANCE,
1615-
actualTemplate.mappings().string())) {
1616-
actualMappings = parser.map();
1617-
} catch (IOException e) {
1618-
throw new AssertionError(e);
1619-
}
1620-
try (XContentParser parser = XContentType.JSON.xContent()
1621-
.createParser(new NamedXContentRegistry(List.of()), LoggingDeprecationHandler.INSTANCE,
1622-
expectedTemplate.mappings().string())) {
1623-
expectedMappings = parser.map();
1624-
} catch (IOException e) {
1625-
throw new AssertionError(e);
1626-
}
1627-
1628-
if (actualMappings.size() == 1 && actualMappings.containsKey(MapperService.SINGLE_MAPPING_NAME)) {
1629-
actualMappings = (Map<String, Object>) actualMappings.get(MapperService.SINGLE_MAPPING_NAME);
1630-
}
1631-
1632-
if (expectedMappings.size() == 1 && expectedMappings.containsKey(MapperService.SINGLE_MAPPING_NAME)) {
1633-
expectedMappings = (Map<String, Object>) expectedMappings.get(MapperService.SINGLE_MAPPING_NAME);
1634-
}
1635-
1636-
assertThat(actualMappings, equalTo(expectedMappings));
1637-
}
1638-
}
1591+
assertTrue(Objects.equals(actual, expected));
16391592
}
16401593

16411594
// Composable index template with data_stream definition need _timestamp meta field mapper,

0 commit comments

Comments
 (0)