/** * This file is part of Graylog. * * Graylog is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * Graylog 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 * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with Graylog. If not, see <http://www.gnu.org/licenses/>. */ package org.graylog2.bundles; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.mongodb.BasicDBObject; import org.graylog2.dashboards.DashboardImpl; import org.graylog2.dashboards.DashboardService; import org.graylog2.dashboards.widgets.DashboardWidgetCreator; import org.graylog2.database.NotFoundException; import org.graylog2.grok.GrokPatternService; import org.graylog2.inputs.InputService; import org.graylog2.streams.OutputService; import org.graylog2.streams.StreamService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.inject.Inject; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Set; public class BundleExporter { private static final Logger LOG = LoggerFactory.getLogger(BundleExporter.class); private final InputService inputService; private final StreamService streamService; private final OutputService outputService; private final DashboardService dashboardService; private final DashboardWidgetCreator dashboardWidgetCreator; private final GrokPatternService grokPatternService; private Set<String> streamSet = new HashSet<>(); @Inject public BundleExporter(final InputService inputService, final StreamService streamService, final OutputService outputService, final DashboardService dashboardService, final DashboardWidgetCreator dashboardWidgetCreator, final GrokPatternService grokPatternService) { this.inputService = inputService; this.streamService = streamService; this.outputService = outputService; this.dashboardService = dashboardService; this.dashboardWidgetCreator = dashboardWidgetCreator; this.grokPatternService = grokPatternService; } public ConfigurationBundle export(final ExportBundle exportBundle) { final ConfigurationBundle configurationBundle = new ConfigurationBundle(); streamSet = new HashSet<>(exportBundle.getStreams()); final Set<Dashboard> dashboards = exportDashboards(exportBundle.getDashboards()); final Set<Output> outputs = exportOutputs(exportBundle.getOutputs()); final Set<Stream> streams = exportStreams(streamSet); final Set<GrokPattern> grokPatterns = exportGrokPatterns(exportBundle.getGrokPatterns()); final Set<Input> inputs = exportInputs(exportBundle.getInputs()); configurationBundle.setName(exportBundle.getName()); configurationBundle.setCategory(exportBundle.getCategory()); configurationBundle.setDescription(exportBundle.getDescription()); configurationBundle.setGrokPatterns(grokPatterns); configurationBundle.setInputs(inputs); configurationBundle.setStreams(streams); configurationBundle.setOutputs(outputs); configurationBundle.setDashboards(dashboards); return configurationBundle; } private Set<GrokPattern> exportGrokPatterns(final Set<String> grokPatterns) { final ImmutableSet.Builder<GrokPattern> grokPatternBuilder = ImmutableSet.builder(); for (String name : grokPatterns) { final GrokPattern grokPattern = exportGrokPattern(name); if (grokPattern != null) { grokPatternBuilder.add(grokPattern); } } return grokPatternBuilder.build(); } private GrokPattern exportGrokPattern(final String grokPatternName) { final org.graylog2.grok.GrokPattern grokPattern; try { grokPattern = grokPatternService.load(grokPatternName); } catch (NotFoundException e) { LOG.debug("Requested grok pattern \"{}\" not found.", grokPatternName); return null; } return GrokPattern.create(grokPattern.name(), grokPattern.pattern()); } private Set<Input> exportInputs(final Set<String> inputs) { final ImmutableSet.Builder<Input> inputBuilder = ImmutableSet.builder(); for (String inputId : inputs) { final Input input = exportInput(inputId); if (input != null) { inputBuilder.add(input); } } return inputBuilder.build(); } private Input exportInput(final String inputId) { final org.graylog2.inputs.Input input; try { input = inputService.find(inputId); } catch (NotFoundException e) { LOG.debug("Requested input {} not found.", inputId); return null; } final Input inputDescription = new Input(); inputDescription.setId(input.getId()); inputDescription.setTitle(input.getTitle()); inputDescription.setType(input.getType()); inputDescription.setGlobal(input.isGlobal()); inputDescription.setConfiguration(input.getConfiguration()); inputDescription.setStaticFields(input.getStaticFields()); inputDescription.setExtractors(exportExtractors(input)); return inputDescription; } private List<Extractor> exportExtractors(org.graylog2.inputs.Input input) { final ImmutableList.Builder<Extractor> extractorBuilder = ImmutableList.builder(); final List<org.graylog2.plugin.inputs.Extractor> extractors = inputService.getExtractors(input); for (org.graylog2.plugin.inputs.Extractor extractor : extractors) { extractorBuilder.add(exportExtractor(extractor)); } return extractorBuilder.build(); } private Extractor exportExtractor(final org.graylog2.plugin.inputs.Extractor extractor) { final Extractor extractorDescription = new Extractor(); extractorDescription.setTitle(extractor.getTitle()); extractorDescription.setType(extractor.getType()); extractorDescription.setConfiguration(extractor.getExtractorConfig()); extractorDescription.setConditionType(extractor.getConditionType()); extractorDescription.setConditionValue(extractor.getConditionValue()); extractorDescription.setCursorStrategy(extractor.getCursorStrategy()); extractorDescription.setOrder(extractor.getOrder().intValue()); extractorDescription.setSourceField(extractor.getSourceField()); extractorDescription.setTargetField(extractor.getTargetField()); final List<org.graylog2.plugin.inputs.Converter> converters = extractor.getConverters(); extractorDescription.setConverters(exportConverters(converters)); return extractorDescription; } private List<Converter> exportConverters(final List<org.graylog2.plugin.inputs.Converter> converters) { final ImmutableList.Builder<Converter> converterBuilder = ImmutableList.builder(); for (org.graylog2.plugin.inputs.Converter converter : converters) { final Converter converterDescription = new Converter(); final org.graylog2.plugin.inputs.Converter.Type type = org.graylog2.plugin.inputs.Converter.Type.valueOf(converter.getType().toUpperCase(Locale.ENGLISH)); converterDescription.setType(type); converterDescription.setConfiguration(converter.getConfig()); converterBuilder.add(converterDescription); } return converterBuilder.build(); } private Set<Stream> exportStreams(final Set<String> streams) { final ImmutableSet.Builder<Stream> streamBuilder = ImmutableSet.builder(); for (String streamId : streams) { final Stream stream = exportStream(streamId); if (stream != null) { streamBuilder.add(stream); } } return streamBuilder.build(); } private Stream exportStream(final String streamId) { final org.graylog2.plugin.streams.Stream stream; try { stream = streamService.load(streamId); } catch (NotFoundException e) { LOG.debug("Requested stream {} not found.", streamId); return null; } final Stream streamDescription = new Stream(); streamDescription.setId(stream.getId()); streamDescription.setTitle(stream.getTitle()); streamDescription.setDescription(stream.getDescription()); streamDescription.setDisabled(stream.getDisabled()); streamDescription.setMatchingType(stream.getMatchingType()); streamDescription.setOutputs(exportOutputReferences(stream.getOutputs())); streamDescription.setStreamRules(exportStreamRules(stream.getStreamRules())); streamDescription.setDefaultStream(stream.isDefaultStream()); return streamDescription; } private List<StreamRule> exportStreamRules(List<org.graylog2.plugin.streams.StreamRule> streamRules) { final ImmutableList.Builder<StreamRule> streamRuleBuilder = ImmutableList.builder(); for (org.graylog2.plugin.streams.StreamRule streamRule : streamRules) { final StreamRule streamRuleDescription = new StreamRule(); streamRuleDescription.setType(streamRule.getType()); streamRuleDescription.setField(streamRule.getField()); streamRuleDescription.setValue(streamRule.getValue()); streamRuleDescription.setInverted(streamRule.getInverted()); streamRuleDescription.setDescription(streamRule.getDescription()); streamRuleBuilder.add(streamRuleDescription); } return streamRuleBuilder.build(); } private Set<String> exportOutputReferences(Set<org.graylog2.plugin.streams.Output> outputs) { final ImmutableSet.Builder<String> outputBuilder = ImmutableSet.builder(); for (org.graylog2.plugin.streams.Output output : outputs) { outputBuilder.add(output.getId()); } return outputBuilder.build(); } private Set<Output> exportOutputs(final Set<String> outputs) { final ImmutableSet.Builder<Output> outputBuilder = ImmutableSet.builder(); for (String outputId : outputs) { final Output output = exportOutput(outputId); if (output != null) { outputBuilder.add(output); } } return outputBuilder.build(); } private Output exportOutput(final String outputId) { final org.graylog2.plugin.streams.Output output; try { output = outputService.load(outputId); } catch (NotFoundException e) { LOG.debug("Requested output {} not found.", outputId); return null; } final Output outputDescription = new Output(); outputDescription.setId(output.getId()); outputDescription.setTitle(output.getTitle()); outputDescription.setType(output.getType()); outputDescription.setConfiguration(output.getConfiguration()); return outputDescription; } private Set<Dashboard> exportDashboards(final Set<String> dashboards) { final ImmutableSet.Builder<Dashboard> dashboardBuilder = ImmutableSet.builder(); for (String dashboardId : dashboards) { final Dashboard dashboard = exportDashboard(dashboardId); if (dashboard != null) { dashboardBuilder.add(dashboard); } } return dashboardBuilder.build(); } private Dashboard exportDashboard(String dashboardId) { final org.graylog2.dashboards.Dashboard dashboard; try { dashboard = dashboardService.load(dashboardId); } catch (NotFoundException e) { LOG.debug("Requested dashboard {} not found.", dashboardId); return null; } final Dashboard dashboardDescription = new Dashboard(); dashboardDescription.setTitle(dashboard.getTitle()); dashboardDescription.setDescription(dashboard.getDescription()); dashboardDescription.setDashboardWidgets(exportDashboardWidgets(dashboard)); return dashboardDescription; } private List<DashboardWidget> exportDashboardWidgets(final org.graylog2.dashboards.Dashboard dashboard) { final ImmutableList.Builder<DashboardWidget> dashboardWidgetBuilder = ImmutableList.builder(); // Add all widgets of this dashboard. final Map<String, Object> fields = dashboard.getFields(); @SuppressWarnings("unchecked") final Map<String, Object> positions = (Map<String, Object>) dashboard.asMap().get("positions"); if (fields.containsKey(DashboardImpl.EMBEDDED_WIDGETS)) { @SuppressWarnings("unchecked") final List<BasicDBObject> embeddedWidgets = (List<BasicDBObject>) fields.get(DashboardImpl.EMBEDDED_WIDGETS); for (BasicDBObject widgetFields : embeddedWidgets) { org.graylog2.dashboards.widgets.DashboardWidget widget; try { widget = dashboardWidgetCreator.fromPersisted(widgetFields); } catch (Exception e) { LOG.warn("Error while exporting widgets of dashboard " + dashboard.getId(), e); continue; } final DashboardWidget dashboardWidgetDescription = new DashboardWidget(); final Map<String, Object> widgetConfig = widget.getConfig(); dashboardWidgetDescription.setDescription(widget.getDescription()); dashboardWidgetDescription.setType(widget.getType()); dashboardWidgetDescription.setConfiguration(widgetConfig); dashboardWidgetDescription.setCacheTime(widget.getCacheTime()); // Mark referenced streams for export final Object streamId = widgetConfig.get("stream_id"); if (streamId instanceof String && streamSet.add((String) streamId)) { LOG.debug("Adding stream {} to export list", streamId); } @SuppressWarnings("unchecked") final Map<String, Integer> widgetPosition = (Map<String, Integer>) positions.get(widget.getId()); if (widgetPosition != null) { final int row = widgetPosition.getOrDefault("row", 0); final int col = widgetPosition.getOrDefault("col", 0); final int height = widgetPosition.getOrDefault("height", 0); final int width = widgetPosition.getOrDefault("width", 0); dashboardWidgetDescription.setRow(row); dashboardWidgetDescription.setCol(col); dashboardWidgetDescription.setHeight(height); dashboardWidgetDescription.setWidth(width); } else { LOG.debug("Couldn't find position for widget {} on dashboard {}, using defaults (0, 0, 0, 0).", widget.getId(), dashboard.getTitle()); dashboardWidgetDescription.setRow(0); dashboardWidgetDescription.setCol(0); dashboardWidgetDescription.setHeight(0); dashboardWidgetDescription.setWidth(0); } dashboardWidgetBuilder.add(dashboardWidgetDescription); } } return dashboardWidgetBuilder.build(); } }