Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2020-2024 Open Text.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.github.cafdataprocessing.elastic.tools;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.io.StringWriter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.opensearch.client.json.JsonpSerializable;
import org.opensearch.client.json.jackson.JacksonJsonpGenerator;
import org.opensearch.client.json.jackson.JacksonJsonpMapper;
import org.opensearch.client.opensearch._types.mapping.DynamicTemplate;
import org.opensearch.client.opensearch._types.mapping.TypeMapping;
import org.opensearch.client.opensearch.indices.TemplateMapping;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.github.cafdataprocessing.elastic.tools.exceptions.GetIndexException;
import com.github.cafdataprocessing.elastic.tools.exceptions.GetTemplatesException;
import com.github.cafdataprocessing.elastic.tools.exceptions.UnexpectedResponseException;
import com.github.cafdataprocessing.elastic.tools.utils.FlatMapUtil;
import com.google.common.collect.MapDifference;
import com.google.common.collect.MapDifference.ValueDifference;
import com.google.common.collect.Maps;
public final class ElasticMappingUpdater
{
private static final Logger LOGGER = LoggerFactory.getLogger(ElasticMappingUpdater.class);
private static final String MAPPING_PROPS_KEY = "properties";
private static final String MAPPING_DYNAMIC_TEMPLATES_KEY = "dynamic_templates";
private static final String MAPPING_TYPE_KEY = "type";
private final ObjectMapper mapper = new ObjectMapper();
private static final Set MODIFIABLE_PROPERTIES = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList(
"boost",
"coerce",
"copy_to",
"eager_global_ordinals",
"fielddata",
"fields",
"ignore_above",
"ignore_malformed",
"meta",
"properties",
"search_analyzer",
"search_quote_analyzer")));
private final ObjectMapper objectMapper;
private final ElasticRequestHandler elasticRequestHandler;
private final boolean dryRun;
/**
* Updates the mapping of indexes matching any templates on the Elasticsearch instances.
*
* @param dryRun If true, the tool lists the mapping changes to the indexes but does not apply them
* @param esHostNames Comma separated list of Elasticsearch hostnames
* @param esProtocol The protocol to connect with Elasticsearch server
* @param esRestPort Elasticsearch REST API port
* @param esUsername Elasticsearch username
* @param esPassword Elasticsearch password
* @param esConnectTimeout Timeout until a new connection is fully established
* @param esSocketTimeout Time of inactivity to wait for packets[data] to be received
* @throws IOException thrown if the elasticsearch request cannot be processed
* @throws GetIndexException thrown if there is an error getting an index
* @throws GetTemplatesException thrown if there is an error getting templates
* @throws UnexpectedResponseException thrown if the elasticsearch response cannot be parsed
*/
public static void update(
final boolean dryRun,
final String esHostNames,
final String esProtocol,
final int esRestPort,
final String esUsername,
final String esPassword,
final int esConnectTimeout,
final int esSocketTimeout
) throws IOException, GetIndexException, GetTemplatesException, UnexpectedResponseException
{
final ElasticMappingUpdater updater
= new ElasticMappingUpdater(dryRun, esHostNames, esProtocol, esRestPort, esUsername, esPassword,
esConnectTimeout, esSocketTimeout);
LOGGER.info("Updating indexes on '{}'. {}", esHostNames,
dryRun ? "This is a dry run. No indexes will actually be updated."
: "Indexes with no mapping conflicts will be updated.");
updater.updateIndexes();
}
private ElasticMappingUpdater(
final boolean dryRun,
final String esHostNames,
final String esProtocol,
final int esRestPort,
final String esUsername,
final String esPassword,
final int esConnectTimeout,
final int esSocketTimeout)
{
this.dryRun = dryRun;
this.objectMapper = new ObjectMapper();
this.objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
final ElasticSettings elasticSettings
= new ElasticSettings(esProtocol, esHostNames, esRestPort, esUsername, esPassword,
esConnectTimeout, esSocketTimeout);
final ElasticMappingUpdaterConfiguration schemaUpdaterConfiguration = new ElasticMappingUpdaterConfiguration(elasticSettings);
elasticRequestHandler = new ElasticRequestHandler(schemaUpdaterConfiguration, objectMapper);
}
private void updateIndexes()
throws IOException, GetIndexException, GetTemplatesException, UnexpectedResponseException
{
final Map templates = elasticRequestHandler.getTemplates();
LOGGER.info("Templates found in Elasticsearch: {}", templates.keySet());
for (final Entry template : templates.entrySet()) {
updateIndexesForTemplate(template.getKey(), template.getValue());
}
}
private void updateIndexesForTemplate(final String templateName, final TemplateMapping template)
throws IOException, GetIndexException, UnexpectedResponseException
{
LOGGER.info("---- Analyzing indexes matching template '{}' ----", templateName);
final List patterns = template.indexPatterns();
final TypeMapping mapping = template.mappings();
if (mapping == null) {
LOGGER.info("No mappings in template '{}'. Indexes for this template will not be updated.", templateName);
return;
}
final Map templateProperties = getObjectAsHashMap(mapping.properties());
// Find all indices that match template patterns
final List indexes = elasticRequestHandler.getIndexNames(patterns);
LOGGER.info("Found {} index(es) that match template '{}'", indexes.size(), templateName);
for (final String indexName : indexes) {
final TypeMapping indexMappings = elasticRequestHandler.getIndexMapping(indexName);
final Map indexProperties = getObjectAsHashMap(indexMappings.properties());
LOGGER.info("Comparing index mapping for '{}'", indexName);
final Map mappingsChanges = getMappingChanges(templateProperties, indexProperties);
final Map mappingsRequest = new HashMap<>();
mappingsRequest.put(MAPPING_PROPS_KEY, mappingsChanges);
// Add all dynamic_templates in template to index mapping
// Empty list will clear all existing dynamic_templates in index mapping
final List