[Monitoring] Add .monitoring-alerts-2 Index Template (elastic/x-pack-elasticsearch#819)
Add the `.monitoring-alerts-2` index template via the exporter. This avoids a very common problem where the user wipes out their monitoring indices manually, which means that the watches would then create an index with a dynamic mappings. This adds a mechanism for posting a template that is not associated with a Resolver (convenient for the forthcoming work _and_ for a future Logstash index). Original commit: elastic/x-pack-elasticsearch@a4cfc48191
This commit is contained in:
parent
4bb9e00dbf
commit
905fa16f81
|
@ -26,9 +26,27 @@ public final class MonitoringTemplateUtils {
|
||||||
*/
|
*/
|
||||||
public static final String[] NEW_DATA_TYPES = { "kibana", "logstash", "beats" };
|
public static final String[] NEW_DATA_TYPES = { "kibana", "logstash", "beats" };
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IDs of templates that can be used with {@linkplain #loadTemplate(String) loadTemplate} that are not managed by a Resolver.
|
||||||
|
* <p>
|
||||||
|
* This will be the complete list of template IDs when resolvers are removed.
|
||||||
|
*/
|
||||||
|
public static final String[] TEMPLATE_IDS = { "alerts" };
|
||||||
|
|
||||||
private MonitoringTemplateUtils() {
|
private MonitoringTemplateUtils() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a template name for any template ID.
|
||||||
|
*
|
||||||
|
* @param id The template identifier.
|
||||||
|
* @return Never {@code null} {@link String} prefixed by ".monitoring-" and the
|
||||||
|
* @see #TEMPLATE_IDS
|
||||||
|
*/
|
||||||
|
public static String templateName(String id) {
|
||||||
|
return ".monitoring-" + id + "-" + TEMPLATE_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
public static String loadTemplate(String id) {
|
public static String loadTemplate(String id) {
|
||||||
String resource = String.format(Locale.ROOT, TEMPLATE_FILE, id);
|
String resource = String.format(Locale.ROOT, TEMPLATE_FILE, id);
|
||||||
return TemplateUtils.loadTemplate(resource, TEMPLATE_VERSION, TEMPLATE_VERSION_PROPERTY);
|
return TemplateUtils.loadTemplate(resource, TEMPLATE_VERSION, TEMPLATE_VERSION_PROPERTY);
|
||||||
|
|
|
@ -531,13 +531,20 @@ public class HttpExporter extends Exporter {
|
||||||
resources.add(new DataTypeMappingHttpResource(resourceOwnerName, templateTimeout, type));
|
resources.add(new DataTypeMappingHttpResource(resourceOwnerName, templateTimeout, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add templates not managed by resolvers
|
||||||
|
for (final String templateId : MonitoringTemplateUtils.TEMPLATE_IDS) {
|
||||||
|
final String templateName = MonitoringTemplateUtils.templateName(templateId);
|
||||||
|
final Supplier<String> templateLoader = () -> MonitoringTemplateUtils.loadTemplate(templateId);
|
||||||
|
|
||||||
|
resources.add(new TemplateHttpResource(resourceOwnerName, templateTimeout, templateName, templateLoader));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: when resolvers are removed, all templates managed by this loop should be included in the TEMPLATE_IDS loop above
|
||||||
for (final MonitoringIndexNameResolver resolver : resolvers) {
|
for (final MonitoringIndexNameResolver resolver : resolvers) {
|
||||||
final String templateName = resolver.templateName();
|
final String templateName = resolver.templateName();
|
||||||
|
|
||||||
// ignore duplicates
|
// ignore duplicates
|
||||||
if (templateNames.contains(templateName) == false) {
|
if (templateNames.add(templateName)) {
|
||||||
templateNames.add(templateName);
|
|
||||||
|
|
||||||
resources.add(new TemplateHttpResource(resourceOwnerName, templateTimeout, templateName, resolver::template));
|
resources.add(new TemplateHttpResource(resourceOwnerName, templateTimeout, templateName, resolver::template));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,6 +145,14 @@ public class LocalExporter extends Exporter implements ClusterStateListener, Cle
|
||||||
final Map<String, String> templates = StreamSupport.stream(new ResolversRegistry(Settings.EMPTY).spliterator(), false)
|
final Map<String, String> templates = StreamSupport.stream(new ResolversRegistry(Settings.EMPTY).spliterator(), false)
|
||||||
.collect(Collectors.toMap(MonitoringIndexNameResolver::templateName, MonitoringIndexNameResolver::template, (a, b) -> a));
|
.collect(Collectors.toMap(MonitoringIndexNameResolver::templateName, MonitoringIndexNameResolver::template, (a, b) -> a));
|
||||||
|
|
||||||
|
// templates not managed by resolvers
|
||||||
|
// TODO: this should just become "templates" when we remove resolvers (and the above templates will disappear as a result)
|
||||||
|
final Map<String, String> nonResolverTemplates = Arrays.stream(MonitoringTemplateUtils.TEMPLATE_IDS)
|
||||||
|
.collect(Collectors.toMap(MonitoringTemplateUtils::templateName, MonitoringTemplateUtils::loadTemplate));
|
||||||
|
|
||||||
|
// add templates that don't come from resolvers
|
||||||
|
templates.putAll(nonResolverTemplates);
|
||||||
|
|
||||||
boolean setup = true;
|
boolean setup = true;
|
||||||
|
|
||||||
// elected master node needs to setup templates; non-master nodes need to wait for it to be setup
|
// elected master node needs to setup templates; non-master nodes need to wait for it to be setup
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
{
|
||||||
|
"template": ".monitoring-alerts-${monitoring.template.version}",
|
||||||
|
"settings": {
|
||||||
|
"index": {
|
||||||
|
"number_of_shards": 1,
|
||||||
|
"number_of_replicas": 1,
|
||||||
|
"codec": "best_compression"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"mappings": {
|
||||||
|
"doc": {
|
||||||
|
"properties": {
|
||||||
|
"timestamp": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"update_timestamp": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"resolved_timestamp": {
|
||||||
|
"type": "date"
|
||||||
|
},
|
||||||
|
"prefix": {
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
"message": {
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
"suffix": {
|
||||||
|
"type": "text"
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"dynamic": false,
|
||||||
|
"properties": {
|
||||||
|
"cluster_uuid": {
|
||||||
|
"type": "keyword"
|
||||||
|
},
|
||||||
|
"link": {
|
||||||
|
"type": "keyword"
|
||||||
|
},
|
||||||
|
"severity": {
|
||||||
|
"type": "short"
|
||||||
|
},
|
||||||
|
"type": {
|
||||||
|
"type": "keyword"
|
||||||
|
},
|
||||||
|
"version": {
|
||||||
|
"type": "keyword"
|
||||||
|
},
|
||||||
|
"watch": {
|
||||||
|
"type": "keyword"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"version": 50400
|
||||||
|
}
|
|
@ -43,7 +43,7 @@ public class HttpExporterResourceTests extends AbstractPublishableHttpResourceTe
|
||||||
* kibana, logstash, beats
|
* kibana, logstash, beats
|
||||||
*/
|
*/
|
||||||
private final int EXPECTED_TYPES = MonitoringTemplateUtils.NEW_DATA_TYPES.length;
|
private final int EXPECTED_TYPES = MonitoringTemplateUtils.NEW_DATA_TYPES.length;
|
||||||
private final int EXPECTED_TEMPLATES = 5;
|
private final int EXPECTED_TEMPLATES = 6;
|
||||||
|
|
||||||
private final RestClient client = mock(RestClient.class);
|
private final RestClient client = mock(RestClient.class);
|
||||||
private final Response versionResponse = mock(Response.class);
|
private final Response versionResponse = mock(Response.class);
|
||||||
|
|
|
@ -315,7 +315,7 @@ public class HttpExporterTests extends ESTestCase {
|
||||||
equalTo(version + typeMappings.size() + templates.size() + pipelines.size() + bwc.size()));
|
equalTo(version + typeMappings.size() + templates.size() + pipelines.size() + bwc.size()));
|
||||||
assertThat(version, equalTo(1));
|
assertThat(version, equalTo(1));
|
||||||
assertThat(typeMappings, hasSize(MonitoringTemplateUtils.NEW_DATA_TYPES.length));
|
assertThat(typeMappings, hasSize(MonitoringTemplateUtils.NEW_DATA_TYPES.length));
|
||||||
assertThat(templates, hasSize(5));
|
assertThat(templates, hasSize(6));
|
||||||
assertThat(pipelines, hasSize(useIngest ? 1 : 0));
|
assertThat(pipelines, hasSize(useIngest ? 1 : 0));
|
||||||
assertThat(bwc, hasSize(1));
|
assertThat(bwc, hasSize(1));
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.elasticsearch.xpack.monitoring.MonitoringService;
|
||||||
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
|
import org.elasticsearch.xpack.monitoring.MonitoringSettings;
|
||||||
import org.elasticsearch.xpack.monitoring.client.MonitoringClient;
|
import org.elasticsearch.xpack.monitoring.client.MonitoringClient;
|
||||||
import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc;
|
import org.elasticsearch.xpack.monitoring.exporter.MonitoringDoc;
|
||||||
|
import org.elasticsearch.xpack.monitoring.exporter.MonitoringTemplateUtils;
|
||||||
import org.elasticsearch.xpack.monitoring.resolver.MonitoringIndexNameResolver;
|
import org.elasticsearch.xpack.monitoring.resolver.MonitoringIndexNameResolver;
|
||||||
import org.elasticsearch.xpack.monitoring.resolver.ResolversRegistry;
|
import org.elasticsearch.xpack.monitoring.resolver.ResolversRegistry;
|
||||||
import org.elasticsearch.xpack.security.Security;
|
import org.elasticsearch.xpack.security.Security;
|
||||||
|
@ -54,6 +55,7 @@ import java.io.OutputStream;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
@ -253,16 +255,30 @@ public abstract class MonitoringIntegTestCase extends ESIntegTestCase {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected List<Tuple<String, String>> monitoringTemplates() {
|
protected List<Tuple<String, String>> monitoringTemplates() {
|
||||||
return StreamSupport.stream(new ResolversRegistry(Settings.EMPTY).spliterator(), false)
|
final List<Tuple<String, String>> templates = Arrays.stream(MonitoringTemplateUtils.TEMPLATE_IDS)
|
||||||
|
.map(id -> new Tuple<>(MonitoringTemplateUtils.templateName(id), MonitoringTemplateUtils.loadTemplate(id)))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
// TODO: remove this when we remove resolvers
|
||||||
|
templates.addAll(StreamSupport.stream(new ResolversRegistry(Settings.EMPTY).spliterator(), false)
|
||||||
.map((resolver) -> new Tuple<>(resolver.templateName(), resolver.template()))
|
.map((resolver) -> new Tuple<>(resolver.templateName(), resolver.template()))
|
||||||
.distinct()
|
.distinct()
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList()));
|
||||||
|
|
||||||
|
return templates;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<String> monitoringTemplateNames() {
|
protected Set<String> monitoringTemplateNames() {
|
||||||
return StreamSupport.stream(new ResolversRegistry(Settings.EMPTY).spliterator(), false)
|
final Set<String> templates = Arrays.stream(MonitoringTemplateUtils.TEMPLATE_IDS)
|
||||||
.map(MonitoringIndexNameResolver::templateName)
|
.map(MonitoringTemplateUtils::templateName)
|
||||||
.collect(Collectors.toSet());
|
.collect(Collectors.toSet());
|
||||||
|
|
||||||
|
// TODO: remove this when we remove resolvers
|
||||||
|
templates.addAll(StreamSupport.stream(new ResolversRegistry(Settings.EMPTY).spliterator(), false)
|
||||||
|
.map(MonitoringIndexNameResolver::templateName)
|
||||||
|
.collect(Collectors.toSet()));
|
||||||
|
|
||||||
|
return templates;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertTemplateInstalled(String name) {
|
protected void assertTemplateInstalled(String name) {
|
||||||
|
|
Loading…
Reference in New Issue