Skip to content

Commit fc4c57b

Browse files
US397427: Stop using existing OpenSearch Java High Level REST Client (#39)
1 parent abdd72c commit fc4c57b

File tree

7 files changed

+554
-784
lines changed

7 files changed

+554
-784
lines changed

elastic-mapping-updater/pom.xml

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@
5050
<groupId>com.google.guava</groupId>
5151
<artifactId>guava</artifactId>
5252
</dependency>
53+
<dependency>
54+
<groupId>jakarta.json</groupId>
55+
<artifactId>jakarta.json-api</artifactId>
56+
</dependency>
5357
<dependency>
5458
<groupId>org.apache.commons</groupId>
5559
<artifactId>commons-lang3</artifactId>
@@ -66,21 +70,13 @@
6670
<groupId>org.apache.httpcomponents</groupId>
6771
<artifactId>httpcore</artifactId>
6872
</dependency>
69-
<dependency>
70-
<groupId>org.opensearch</groupId>
71-
<artifactId>opensearch</artifactId>
72-
</dependency>
73-
<dependency>
74-
<groupId>org.opensearch</groupId>
75-
<artifactId>opensearch-x-content</artifactId>
76-
</dependency>
7773
<dependency>
7874
<groupId>org.opensearch.client</groupId>
7975
<artifactId>opensearch-rest-client</artifactId>
8076
</dependency>
8177
<dependency>
8278
<groupId>org.opensearch.client</groupId>
83-
<artifactId>opensearch-rest-high-level-client</artifactId>
79+
<artifactId>opensearch-java</artifactId>
8480
</dependency>
8581
<dependency>
8682
<groupId>org.slf4j</groupId>

elastic-mapping-updater/src/main/java/com/github/cafdataprocessing/elastic/tools/ElasticMappingUpdater.java

Lines changed: 55 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -20,24 +20,31 @@
2020
import java.util.Arrays;
2121
import java.util.Collections;
2222
import java.util.HashMap;
23+
import java.util.LinkedHashMap;
2324
import java.util.HashSet;
2425
import java.util.List;
2526
import java.util.Map;
26-
import java.util.Optional;
27+
import java.util.Map.Entry;
2728
import java.util.Set;
2829
import java.util.regex.Pattern;
2930
import java.util.stream.Collectors;
31+
import java.io.StringWriter;
3032

3133
import org.apache.commons.lang3.StringUtils;
32-
import org.opensearch.client.indices.GetIndexResponse;
33-
import org.opensearch.client.indices.IndexTemplateMetadata;
34-
import org.opensearch.cluster.metadata.MappingMetadata;
3534
import org.slf4j.Logger;
3635
import org.slf4j.LoggerFactory;
36+
import org.opensearch.client.json.JsonpSerializable;
37+
import org.opensearch.client.json.jackson.JacksonJsonpGenerator;
38+
import org.opensearch.client.json.jackson.JacksonJsonpMapper;
39+
import org.opensearch.client.opensearch._types.mapping.DynamicTemplate;
40+
import org.opensearch.client.opensearch._types.mapping.TypeMapping;
41+
import org.opensearch.client.opensearch.indices.TemplateMapping;
3742

3843
import com.fasterxml.jackson.annotation.PropertyAccessor;
3944
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
45+
import com.fasterxml.jackson.core.JsonFactory;
4046
import com.fasterxml.jackson.core.JsonProcessingException;
47+
import com.fasterxml.jackson.core.type.TypeReference;
4148
import com.fasterxml.jackson.databind.ObjectMapper;
4249
import com.github.cafdataprocessing.elastic.tools.exceptions.GetIndexException;
4350
import com.github.cafdataprocessing.elastic.tools.exceptions.GetTemplatesException;
@@ -55,6 +62,8 @@ public final class ElasticMappingUpdater
5562
private static final String MAPPING_DYNAMIC_TEMPLATES_KEY = "dynamic_templates";
5663
private static final String MAPPING_TYPE_KEY = "type";
5764

65+
private final ObjectMapper mapper = new ObjectMapper();
66+
5867
private static final Set<String> MODIFIABLE_PROPERTIES = Collections.unmodifiableSet(
5968
new HashSet<>(Arrays.asList(
6069
"boost",
@@ -135,66 +144,53 @@ private ElasticMappingUpdater(
135144
private void updateIndexes()
136145
throws IOException, GetIndexException, GetTemplatesException, UnexpectedResponseException
137146
{
138-
final List<IndexTemplateMetadata> templates = elasticRequestHandler.getTemplates();
139-
LOGGER.info("Templates found in Elasticsearch: {}",
140-
templates.stream().map(template -> template.name()).collect(Collectors.toList()));
141-
for (final IndexTemplateMetadata template : templates) {
142-
updateIndexesForTemplate(template);
147+
final Map<String, TemplateMapping> templates = elasticRequestHandler.getTemplates();
148+
LOGGER.info("Templates found in Elasticsearch: {}", templates.keySet());
149+
for (final Entry<String, TemplateMapping> template : templates.entrySet()) {
150+
updateIndexesForTemplate(template.getKey(), template.getValue());
143151
}
144152
}
145153

146-
private void updateIndexesForTemplate(final IndexTemplateMetadata template)
147-
throws IOException, GetIndexException, GetTemplatesException, UnexpectedResponseException
154+
private void updateIndexesForTemplate(final String templateName, final TemplateMapping template)
155+
throws IOException, GetIndexException, UnexpectedResponseException
148156
{
149-
final String templateName = template.name();
150157
LOGGER.info("---- Analyzing indexes matching template '{}' ----", templateName);
151158

152-
final List<String> patterns = template.patterns();
159+
final List<String> patterns = template.indexPatterns();
153160

154-
final MappingMetadata mapping = template.mappings();
161+
final TypeMapping mapping = template.mappings();
155162
if (mapping == null) {
156163
LOGGER.info("No mappings in template '{}'. Indexes for this template will not be updated.", templateName);
157164
return;
158165
}
159166

160-
final Map<String, Object> templateTypeMappings = mapping.getSourceAsMap();
161-
162-
final Object templateProperties = Optional
163-
.ofNullable(templateTypeMappings.get(MAPPING_PROPS_KEY))
164-
.orElseGet(Collections::emptyMap);
167+
final Map<String, Object> templateProperties = getObjectAsHashMap(mapping.properties());
165168

166169
// Find all indices that match template patterns
167170
final List<String> indexes = elasticRequestHandler.getIndexNames(patterns);
168171
LOGGER.info("Found {} index(es) that match template '{}'", indexes.size(), templateName);
169172
for (final String indexName : indexes) {
170-
GetIndexResponse getIndexResponse = elasticRequestHandler.getIndex(indexName);
171-
MappingMetadata indexMappings = getIndexResponse.getMappings().get(indexName);
172-
Map<String, Object> indexTypeMappings = indexMappings.getSourceAsMap();
173+
final TypeMapping indexMappings = elasticRequestHandler.getIndexMapping(indexName);
174+
final Map<String, Object> indexProperties = getObjectAsHashMap(indexMappings.properties());
173175

174176
LOGGER.info("Comparing index mapping for '{}'", indexName);
175177

176-
final Object indexProperties = Optional
177-
.ofNullable(indexTypeMappings.get(MAPPING_PROPS_KEY))
178-
.orElseGet(Collections::emptyMap);
179-
180-
@SuppressWarnings("unchecked")
181-
final Map<String, Object> mappingsChanges = getMappingChanges(
182-
(Map<String, Object>) templateProperties,
183-
(Map<String, Object>) indexProperties);
178+
final Map<String, Object> mappingsChanges = getMappingChanges(templateProperties, indexProperties);
184179

185180
final Map<String, Object> mappingsRequest = new HashMap<>();
186181
mappingsRequest.put(MAPPING_PROPS_KEY, mappingsChanges);
187182

188183
// Add all dynamic_templates in template to index mapping
189-
@SuppressWarnings("unchecked")
190-
final List<Object> dynamicTemplatesInTemplate = (List<Object>) Optional
191-
.ofNullable(templateTypeMappings.get(MAPPING_DYNAMIC_TEMPLATES_KEY))
192-
.orElseGet(Collections::emptyList); // Empty list will clear all existing dynamic_templates in index mapping
184+
// Empty list will clear all existing dynamic_templates in index mapping
185+
final List<Object> dynamicTemplatesInTemplate = new ArrayList<>();
186+
for (final Map<String, DynamicTemplate> t : mapping.dynamicTemplates()) {
187+
dynamicTemplatesInTemplate.add(getObjectAsHashMap(t));
188+
}
193189

194-
@SuppressWarnings("unchecked")
195-
final List<Object> dynamicTemplatesInIndex = (List<Object>) Optional
196-
.ofNullable(indexTypeMappings.get(MAPPING_DYNAMIC_TEMPLATES_KEY))
197-
.orElseGet(Collections::emptyList);
190+
final List<Object> dynamicTemplatesInIndex = new ArrayList<>();
191+
for (final Map<String, DynamicTemplate> t : indexMappings.dynamicTemplates()) {
192+
dynamicTemplatesInIndex.add(getObjectAsHashMap(t));
193+
}
198194

199195
final List<Object> dynamicTemplatesUpdates = new ArrayList<>(dynamicTemplatesInTemplate);
200196

@@ -353,8 +349,8 @@ private Map<String, Object> getMappingChanges(final Map<String, Object> template
353349
// Check if 'type' has changed for object/nested properties
354350
final Map<String, ValueDifference<Object>> typeDifferences = entriesDiffering.entrySet().stream()
355351
.filter(e -> ((Map<?, ?>) (e.getValue().leftValue())).containsKey(MAPPING_PROPS_KEY)
356-
&& (((Map<?, ?>) (e.getValue().leftValue())).containsKey(MAPPING_TYPE_KEY)
357-
|| ((Map<?, ?>) (e.getValue().rightValue())).containsKey(MAPPING_TYPE_KEY)))
352+
&& (!((Map<?, ?>) (e.getValue().leftValue())).get(MAPPING_TYPE_KEY).equals("object")
353+
|| !((Map<?, ?>) (e.getValue().rightValue())).get(MAPPING_TYPE_KEY).equals("object")))
358354
.collect(Collectors.toMap(e -> e.getKey(), e -> e.getValue()));
359355

360356
if (!typeDifferences.isEmpty()) {
@@ -406,7 +402,7 @@ private Map<String, Object> getMappingChanges(final Map<String, Object> template
406402
return mappingsChanges;
407403
}
408404

409-
private boolean hasDynamicTemplateChanged(List<Object> dynamicTemplatesInTemplate, List<Object> dynamicTemplatesInIndex)
405+
private boolean hasDynamicTemplateChanged(final List<Object> dynamicTemplatesInTemplate, final List<Object> dynamicTemplatesInIndex)
410406
{
411407
if (dynamicTemplatesInTemplate.size() != dynamicTemplatesInIndex.size()) {
412408
return true;
@@ -451,4 +447,22 @@ private void removeUnsupportedFieldChange(final Map<String, Object> mappingsChan
451447
}
452448
}
453449

450+
private Map<String,Object> getObjectAsHashMap(final Map<String, ? extends JsonpSerializable> obj) throws JsonProcessingException, IOException
451+
{
452+
final Map<String, Object> mapFromString = new LinkedHashMap<>();
453+
for (final Entry<String, ? extends JsonpSerializable> val : obj.entrySet()) {
454+
final String result = "{\"" + val.getKey() + "\":" + getStringFromObject(val.getValue()) + "}";
455+
mapFromString.putAll(mapper.readValue(result, new TypeReference<Map<String, Object>>(){}));
456+
}
457+
return mapFromString;
458+
}
459+
460+
private String getStringFromObject(final JsonpSerializable value) throws IOException
461+
{
462+
final StringWriter writer = new StringWriter();
463+
try (final JacksonJsonpGenerator generator = new JacksonJsonpGenerator(new JsonFactory().createGenerator(writer))) {
464+
value.serialize(generator, new JacksonJsonpMapper());
465+
}
466+
return writer.toString();
467+
}
454468
}

elastic-mapping-updater/src/main/java/com/github/cafdataprocessing/elastic/tools/ElasticRequestHandler.java

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import java.io.IOException;
1919
import java.io.InputStream;
20+
import java.io.StringReader;
2021
import java.nio.charset.StandardCharsets;
2122
import java.util.Collections;
2223
import java.util.List;
@@ -31,13 +32,6 @@
3132
import org.opensearch.client.Response;
3233
import org.opensearch.client.ResponseException;
3334
import org.opensearch.client.RestClient;
34-
import org.opensearch.client.indices.GetIndexResponse;
35-
import org.opensearch.client.indices.GetIndexTemplatesResponse;
36-
import org.opensearch.client.indices.IndexTemplateMetadata;
37-
import org.opensearch.common.xcontent.NamedXContentRegistry;
38-
import org.opensearch.common.xcontent.XContentFactory;
39-
import org.opensearch.common.xcontent.XContentParser;
40-
import org.opensearch.common.xcontent.XContentType;
4135
import org.slf4j.Logger;
4236
import org.slf4j.LoggerFactory;
4337

@@ -48,6 +42,16 @@
4842
import com.github.cafdataprocessing.elastic.tools.exceptions.UnexpectedResponseException;
4943
import com.google.common.net.UrlEscapers;
5044

45+
import jakarta.json.Json;
46+
import jakarta.json.JsonObject;
47+
import jakarta.json.JsonReader;
48+
import jakarta.json.stream.JsonParser;
49+
import org.opensearch.client.json.jackson.JacksonJsonpMapper;
50+
import org.opensearch.client.opensearch._types.mapping.TypeMapping;
51+
import org.opensearch.client.opensearch.indices.GetTemplateResponse;
52+
import org.opensearch.client.opensearch.indices.TemplateMapping;
53+
import org.opensearch.client.util.ApiTypeHelper;
54+
5155
final class ElasticRequestHandler
5256
{
5357
private static final Logger LOGGER = LoggerFactory.getLogger(ElasticRequestHandler.class);
@@ -60,7 +64,7 @@ public ElasticRequestHandler(final ElasticMappingUpdaterConfiguration schemaUpda
6064
this.elasticClient = ElasticProvider.getClient(schemaUpdaterConfig.getElasticSettings());
6165
}
6266

63-
List<IndexTemplateMetadata> getTemplates()
67+
Map<String, TemplateMapping> getTemplates()
6468
throws IOException, GetTemplatesException
6569
{
6670
LOGGER.debug("Getting templates...");
@@ -70,11 +74,13 @@ List<IndexTemplateMetadata> getTemplates()
7074
final int statusCode = response.getStatusLine().getStatusCode();
7175
if (statusCode == 200) {
7276
try (final InputStream resultJsonStream = response.getEntity().getContent();
73-
final XContentParser parser
74-
= XContentFactory.xContent(XContentType.JSON).createParser(NamedXContentRegistry.EMPTY, null, resultJsonStream)) {
75-
final GetIndexTemplatesResponse getTemplatesResponse = GetIndexTemplatesResponse.fromXContent(parser);
76-
final List<IndexTemplateMetadata> templates = getTemplatesResponse.getIndexTemplates();
77-
return templates;
77+
final JsonParser jsonValueParser = Json.createParser(resultJsonStream)) {
78+
ApiTypeHelper.DANGEROUS_disableRequiredPropertiesCheck(true);
79+
final GetTemplateResponse getTemplatesResponse =
80+
GetTemplateResponse._DESERIALIZER.deserialize(jsonValueParser, new JacksonJsonpMapper());
81+
final Map<String, TemplateMapping> indexTemplates = getTemplatesResponse.result();
82+
ApiTypeHelper.DANGEROUS_disableRequiredPropertiesCheck(false);
83+
return indexTemplates;
7884
}
7985
} else {
8086
throw new GetTemplatesException(String.format("Error getting templates. Status code: %s, response: %s",
@@ -110,19 +116,22 @@ List<String> getIndexNames(final List<String> indexNamePatterns) throws Unexpect
110116
}
111117
}
112118

113-
public GetIndexResponse getIndex(final String indexName) throws IOException, GetIndexException
119+
public TypeMapping getIndexMapping(final String indexName) throws IOException, GetIndexException
114120
{
115-
LOGGER.debug("Getting index {}...", indexName);
121+
LOGGER.debug("Getting index mapping for: {}...", indexName);
116122
final Request request = new Request("GET", "/" + UrlEscapers.urlPathSegmentEscaper().escape(indexName));
117123
final Response response = elasticClient.performRequest(request);
118124

119125
final int statusCode = response.getStatusLine().getStatusCode();
120126
if (statusCode == 200) {
121-
try (final InputStream resultJsonStream = response.getEntity().getContent();
122-
final XContentParser parser
123-
= XContentFactory.xContent(XContentType.JSON).createParser(NamedXContentRegistry.EMPTY, null, resultJsonStream)) {
124-
return GetIndexResponse.fromXContent(parser);
125-
}
127+
final JsonReader jsonReader = Json.createReader(new StringReader(EntityUtils.toString(response.getEntity())));
128+
final JsonObject mappings = jsonReader.readObject().getJsonObject(indexName).getJsonObject("mappings");
129+
130+
final JsonParser jsonMappingParser = Json.createParser(new StringReader(mappings.toString()));
131+
ApiTypeHelper.DANGEROUS_disableRequiredPropertiesCheck(true);
132+
final TypeMapping mapping = TypeMapping._DESERIALIZER.deserialize(jsonMappingParser, new JacksonJsonpMapper());
133+
ApiTypeHelper.DANGEROUS_disableRequiredPropertiesCheck(false);
134+
return mapping;
126135
} else {
127136
throw new GetIndexException(String.format("Error getting index '%s'. Status code: %s, response: %s",
128137
indexName, statusCode, EntityUtils.toString(response.getEntity())));

0 commit comments

Comments
 (0)