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 Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
package org.elasticsearch.xpack.core.template;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.ParameterizedMessage;
import org.elasticsearch.ElasticsearchParseException;
import org.elasticsearch.Version;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.metadata.IndexTemplateMetadata;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.bytes.BytesReference;
import org.elasticsearch.common.collect.ImmutableOpenMap;
import org.elasticsearch.common.compress.CompressedXContent;
import org.elasticsearch.common.io.Streams;
import org.elasticsearch.common.xcontent.LoggingDeprecationHandler;
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentHelper;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.common.xcontent.json.JsonXContent;
import java.io.IOException;
import java.util.Collections;
import java.util.Map;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import static org.elasticsearch.common.xcontent.XContentHelper.convertToMap;
/**
* Handling versioned templates for time-based indices in x-pack
*/
public class TemplateUtils {
private TemplateUtils() {}
/**
* Loads a JSON template as a resource and puts it into the provided map
*/
public static void loadTemplateIntoMap(String resource, Map map, String templateName, String version,
String versionProperty, Logger logger) {
final String template = loadTemplate(resource, version, versionProperty);
try (XContentParser parser = XContentFactory.xContent(XContentType.JSON)
.createParser(NamedXContentRegistry.EMPTY, LoggingDeprecationHandler.INSTANCE, template)) {
map.put(templateName, IndexTemplateMetadata.Builder.fromXContent(parser, templateName));
} catch (IOException e) {
// TODO: should we handle this with a thrown exception?
logger.error("Error loading template [{}] as part of metadata upgrading", templateName);
}
}
/**
* Loads a built-in template and returns its source.
*/
public static String loadTemplate(String resource, String version, String versionProperty) {
return loadTemplate(resource, version, versionProperty, Collections.emptyMap());
}
/**
* Loads a built-in template and returns its source after replacing given variables.
*/
public static String loadTemplate(String resource, String version, String versionProperty, Map variables) {
try {
String source = load(resource);
source = replaceVariables(source, version, versionProperty, variables);
validate(source);
return source;
} catch (Exception e) {
throw new IllegalArgumentException("Unable to load template [" + resource + "]", e);
}
}
/**
* Loads a resource from the classpath and returns it as a {@link BytesReference}
*/
public static String load(String name) throws IOException {
return Streams.readFully(TemplateUtils.class.getResourceAsStream(name)).utf8ToString();
}
/**
* Parses and validates that the source is not empty.
*/
public static void validate(String source) {
if (source == null) {
throw new ElasticsearchParseException("Template must not be null");
}
if (Strings.isEmpty(source)) {
throw new ElasticsearchParseException("Template must not be empty");
}
try {
XContentHelper.convertToMap(JsonXContent.jsonXContent, source, false);
} catch (Exception e) {
throw new ElasticsearchParseException("Invalid template", e);
}
}
private static String replaceVariables(String input, String version, String versionProperty, Map variables) {
String template = replaceVariable(input, versionProperty, version);
for (Map.Entry variable : variables.entrySet()) {
template = replaceVariable(template, variable.getKey(), variable.getValue());
}
return template;
}
/**
* Replaces all occurences of given variable with the value
*/
public static String replaceVariable(String input, String variable, String value) {
return Pattern.compile("${" + variable + "}", Pattern.LITERAL)
.matcher(input)
.replaceAll(value);
}
/**
* Checks if a versioned template exists, and if it exists checks if the version is greater than or equal to the current version.
* @param templateName Name of the index template
* @param state Cluster state
*/
public static boolean checkTemplateExistsAndVersionIsGTECurrentVersion(String templateName, ClusterState state) {
IndexTemplateMetadata templateMetadata = state.metadata().templates().get(templateName);
if (templateMetadata == null) {
return false;
}
return templateMetadata.version() != null && templateMetadata.version() >= Version.CURRENT.id;
}
/**
* Checks if a versioned template exists, and if it exists checks if it is up-to-date with current version.
* @param versionKey The property in the mapping's _meta field which stores the version info
* @param templateName Name of the index template
* @param state Cluster state
* @param logger Logger
*/
public static boolean checkTemplateExistsAndIsUpToDate(
String templateName, String versionKey, ClusterState state, Logger logger) {
return checkTemplateExistsAndVersionMatches(templateName, versionKey, state, logger,
Version.CURRENT::equals);
}
/**
* Checks if template with given name exists and if it matches the version predicate given
* @param versionKey The property in the mapping's _meta field which stores the version info
* @param templateName Name of the index template
* @param state Cluster state
* @param logger Logger
* @param predicate Predicate to execute on version check
*/
public static boolean checkTemplateExistsAndVersionMatches(
String templateName, String versionKey, ClusterState state, Logger logger, Predicate predicate) {
IndexTemplateMetadata templateMeta = state.metadata().templates().get(templateName);
if (templateMeta == null) {
return false;
}
ImmutableOpenMap mappings = templateMeta.getMappings();
// check all mappings contain correct version in _meta
// we have to parse the source here which is annoying
for (Object typeMapping : mappings.values().toArray()) {
CompressedXContent typeMappingXContent = (CompressedXContent) typeMapping;
try {
Map typeMappingMap = convertToMap(typeMappingXContent.uncompressed(), false, XContentType.JSON).v2();
// should always contain one entry with key = typename
assert (typeMappingMap.size() == 1);
String key = typeMappingMap.keySet().iterator().next();
// get the actual mapping entries
@SuppressWarnings("unchecked")
Map mappingMap = (Map) typeMappingMap.get(key);
if (containsCorrectVersion(versionKey, mappingMap, predicate) == false) {
return false;
}
} catch (ElasticsearchParseException e) {
logger.error(new ParameterizedMessage(
"Cannot parse the template [{}]", templateName), e);
throw new IllegalStateException("Cannot parse the template " + templateName, e);
}
}
return true;
}
private static boolean containsCorrectVersion(String versionKey, Map typeMappingMap,
Predicate predicate) {
@SuppressWarnings("unchecked")
Map meta = (Map) typeMappingMap.get("_meta");
if (meta == null) {
// pre 5.0, cannot be up to date
return false;
}
return predicate.test(Version.fromString((String) meta.get(versionKey)));
}
}