org.graylog.plugins.sidecar.services.ConfigurationService Maven / Gradle / Ivy
/*
* Copyright (C) 2020 Graylog, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the Server Side Public License, version 1,
* as published by MongoDB, Inc.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* Server Side Public License for more details.
*
* You should have received a copy of the Server Side Public License
* along with this program. If not, see
* .
*/
package org.graylog.plugins.sidecar.services;
import com.mongodb.BasicDBObject;
import com.mongodb.DBCollection;
import freemarker.cache.StringTemplateLoader;
import freemarker.cache.TemplateLoader;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import org.graylog.plugins.sidecar.rest.models.Configuration;
import org.graylog.plugins.sidecar.rest.models.ConfigurationVariable;
import org.graylog.plugins.sidecar.rest.models.Sidecar;
import org.graylog.plugins.sidecar.template.RenderTemplateException;
import org.graylog.plugins.sidecar.template.directives.IndentTemplateDirective;
import org.graylog.plugins.sidecar.template.loader.MongoDbTemplateLoader;
import org.graylog2.bindings.providers.MongoJackObjectMapperProvider;
import org.graylog2.database.MongoConnection;
import org.graylog2.database.PaginatedDbService;
import org.graylog2.database.PaginatedList;
import org.graylog2.search.SearchQuery;
import org.mongojack.DBQuery;
import org.mongojack.DBSort;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.inject.Inject;
import javax.inject.Provider;
import javax.inject.Singleton;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.apache.commons.lang.CharEncoding.UTF_8;
@Singleton
public class ConfigurationService extends PaginatedDbService {
private static final Logger LOG = LoggerFactory.getLogger(ConfigurationService.class);
private final freemarker.template.Configuration templateConfiguration;
private final ConfigurationVariableService configurationVariableService;
private static final String COLLECTION_NAME = "sidecar_configurations";
private final Provider templateConfigurationProvider;
@Inject
public ConfigurationService(MongoConnection mongoConnection,
MongoJackObjectMapperProvider mapper,
ConfigurationVariableService configurationVariableService,
Provider templateConfigurationProvider) {
super(mongoConnection, mapper, Configuration.class, COLLECTION_NAME);
this.templateConfigurationProvider = templateConfigurationProvider;
this.templateConfiguration = createTemplateConfiguration(new MongoDbTemplateLoader(db));
this.configurationVariableService = configurationVariableService;
DBCollection collection = db.getDB().getCollection(COLLECTION_NAME);
collection.createIndex(new BasicDBObject(Configuration.FIELD_ID, 1));
collection.createIndex(new BasicDBObject(Configuration.FIELD_COLLECTOR_ID, 1));
collection.createIndex(new BasicDBObject(Configuration.FIELD_TAGS, 1));
}
private freemarker.template.Configuration createTemplateConfiguration(TemplateLoader templateLoader) {
final freemarker.template.Configuration configuration = templateConfigurationProvider.get();
configuration.setTemplateLoader(templateLoader);
configuration.setSharedVariable("indent", new IndentTemplateDirective());
configuration.setDefaultEncoding(UTF_8);
configuration.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
configuration.setLogTemplateExceptions(false);
return configuration;
}
public Configuration find(String id) {
return db.findOne(DBQuery.is("_id", id));
}
public Configuration findByName(String name) {
return db.findOne(DBQuery.is(Configuration.FIELD_NAME, name));
}
public long count() {
return db.count();
}
public List all() {
try (final Stream collectorConfigurationStream = streamAll()) {
return collectorConfigurationStream.collect(Collectors.toList());
}
}
public PaginatedList findPaginated(SearchQuery searchQuery, int page, int perPage, String sortField, String order) {
final DBQuery.Query dbQuery = searchQuery.toDBQuery();
final DBSort.SortBuilder sortBuilder = getSortBuilder(order, sortField);
return findPaginatedWithQueryAndSort(dbQuery, sortBuilder, page, perPage);
}
public List findByQuery(DBQuery.Query query) {
try (final Stream collectorConfigurationStream = streamQuery(query)) {
return collectorConfigurationStream.collect(Collectors.toList());
}
}
public List findByConfigurationVariable(ConfigurationVariable configurationVariable) {
final DBQuery.Query query = DBQuery.regex(Configuration.FIELD_TEMPLATE, Pattern.compile(Pattern.quote(configurationVariable.fullName())));
return findByQuery(query);
}
public List findByTags(Set tags) {
return findByQuery(DBQuery.in(Configuration.FIELD_TAGS, tags));
}
public void replaceVariableNames(String oldName, String newName) {
final DBQuery.Query query = DBQuery.regex(Configuration.FIELD_TEMPLATE, Pattern.compile(Pattern.quote(oldName)));
List configurations = findByQuery(query);
for (Configuration config : configurations) {
final String newTemplate = config.template().replace(oldName, newName);
db.findAndModify(DBQuery.is("_id", config.id()), new BasicDBObject(),
new BasicDBObject(), false, config.toBuilder().template(newTemplate).build(), true, true);
}
}
@Override
public Configuration save(Configuration configuration) {
return db.findAndModify(DBQuery.is("_id", configuration.id()), new BasicDBObject(),
new BasicDBObject(), false, configuration, true, true);
}
public Configuration copyConfiguration(String id, String name) {
Configuration configuration = find(id);
// Tags are not copied on purpose
return Configuration.createWithoutId(configuration.collectorId(), name, configuration.color(), configuration.template(), Set.of());
}
public Configuration fromRequest(Configuration request) {
return Configuration.createWithoutId(
request.collectorId(),
request.name(),
request.color(),
request.template(),
request.tags());
}
public Configuration fromRequest(String id, Configuration request) {
return Configuration.create(
id,
request.collectorId(),
request.name(),
request.color(),
request.template(),
request.tags());
}
public Configuration renderConfigurationForCollector(Sidecar sidecar, Configuration configuration) throws RenderTemplateException {
Map context = new HashMap<>();
context.put("nodeId", sidecar.nodeId());
context.put("nodeName", sidecar.nodeName());
context.put("sidecarVersion", sidecar.sidecarVersion());
context.put("operatingSystem", sidecar.nodeDetails().operatingSystem());
if (sidecar.nodeDetails().collectorConfigurationDirectory() != null) {
String pathDelim = sidecar.nodeDetails().operatingSystem().equalsIgnoreCase("windows") ? "\\" : "/";
context.put("spoolDir", sidecar.nodeDetails().collectorConfigurationDirectory() + pathDelim + configuration.id());
}
context.put("tags", sidecar.nodeDetails().tags().stream().collect(Collectors.toMap(t -> t, t -> true)));
return Configuration.create(
configuration.id(),
configuration.collectorId(),
configuration.name(),
configuration.color(),
renderTemplate(templateConfiguration, configuration.id(), context),
configuration.tags()
);
}
public String renderPreview(String template) throws RenderTemplateException {
Map context = new HashMap<>();
context.put("nodeId", "");
context.put("nodeName", "");
context.put("sidecarVersion", "");
context.put("operatingSystem", "");
context.put("spoolDir", "");
context.put("tags", Map.of());
String previewName = UUID.randomUUID().toString();
final StringTemplateLoader stringTemplateLoader = new StringTemplateLoader();
stringTemplateLoader.putTemplate(previewName, template);
return renderTemplate(createTemplateConfiguration(stringTemplateLoader), previewName, context);
}
private String renderTemplate(freemarker.template.Configuration config, String templateName, Map sidecarContext) throws RenderTemplateException {
Writer writer = new StringWriter();
final Map context = new HashMap<>();
context.put("sidecar", sidecarContext);
final Map userContext =
configurationVariableService.all().stream().collect(Collectors.toMap(ConfigurationVariable::name, ConfigurationVariable::content));
context.put(ConfigurationVariable.VARIABLE_PREFIX, userContext);
try {
Template compiledTemplate = config.getTemplate(templateName);
compiledTemplate.process(context, writer);
} catch (TemplateException e) {
LOG.error("Failed to render template: " + e.getMessageWithoutStackTop());
throw new RenderTemplateException(e.getFTLInstructionStack(), e);
} catch (IOException e) {
LOG.error("Failed to render template: ", e);
throw new RenderTemplateException(e.getMessage(), e);
}
final String template = writer.toString();
return template.endsWith("\n") ? template : template + "\n";
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy