All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.graylog2.migrations.V20161125142400_EmailAlarmCallbackMigration Maven / Gradle / Ivy

There is a newer version: 5.2.7
Show newest version
/**
 * 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 .
 */
package org.graylog2.migrations;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
import org.graylog.autovalue.WithBeanGetter;
import org.graylog2.alarmcallbacks.AlarmCallbackConfiguration;
import org.graylog2.alarmcallbacks.AlarmCallbackConfigurationService;
import org.graylog2.alarmcallbacks.EmailAlarmCallback;
import org.graylog2.plugin.cluster.ClusterConfigService;
import org.graylog2.plugin.configuration.ConfigurationRequest;
import org.graylog2.plugin.database.Persisted;
import org.graylog2.plugin.database.ValidationException;
import org.graylog2.plugin.streams.Stream;
import org.graylog2.rest.models.alarmcallbacks.requests.CreateAlarmCallbackRequest;
import org.graylog2.streams.StreamService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.inject.Inject;
import java.time.ZonedDateTime;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

public class V20161125142400_EmailAlarmCallbackMigration extends Migration {
    private static final Logger LOG = LoggerFactory.getLogger(V20161125142400_EmailAlarmCallbackMigration.class);

    private final ClusterConfigService clusterConfigService;
    private final StreamService streamService;
    private final AlarmCallbackConfigurationService alarmCallbackService;
    private final EmailAlarmCallback emailAlarmCallback;

    @Inject
    public V20161125142400_EmailAlarmCallbackMigration(ClusterConfigService clusterConfigService, StreamService streamService, AlarmCallbackConfigurationService alarmCallbackService, EmailAlarmCallback emailAlarmCallback) {
        this.clusterConfigService = clusterConfigService;
        this.streamService = streamService;
        this.alarmCallbackService = alarmCallbackService;
        this.emailAlarmCallback = emailAlarmCallback;
    }

    @Override
    public ZonedDateTime createdAt() {
        return ZonedDateTime.parse("2016-11-25T14:24:00Z");
    }

    private boolean hasAlertReceivers(Stream stream) {
        final Map> alertReceivers = stream.getAlertReceivers();
        if (alertReceivers == null || alertReceivers.isEmpty()) {
            return false;
        }

        final List users = alertReceivers.get("users");
        final List emails = alertReceivers.get("emails");
        return users != null && !users.isEmpty() || emails != null && !emails.isEmpty();
    }

    @Override
    public void upgrade() {
        // Do not run again if the migration marker can be found in the database.
        if (clusterConfigService.get(MigrationCompleted.class) != null) {
            return;
        }

        final Map> streamMigrations = this.streamService.loadAll()
                .stream()
                .filter(stream -> this.hasAlertReceivers(stream)
                        && !streamService.getAlertConditions(stream).isEmpty()
                        && alarmCallbackService.getForStream(stream).isEmpty())
                .collect(Collectors.toMap(Persisted::getId, this::migrateStream));
        final boolean allSucceeded = streamMigrations.values()
                .stream()
                .allMatch(Optional::isPresent);

        final long count = streamMigrations.size();
        if (allSucceeded) {
            if (count > 0) {
                LOG.info("Successfully migrated " + count + " streams to include explicit email alarm callback.");
            } else {
                LOG.info("No streams needed to be migrated.");
            }
            this.clusterConfigService.write(MigrationCompleted.create(streamMigrations));
        } else {
            final long errors = streamMigrations.values()
                    .stream()
                    .filter(callbackId -> !callbackId.isPresent())
                    .count();
            LOG.error("Failed migrating " + errors + "/" + count + " streams to include explicit email alarm callback.");
        }
    }

    private Optional migrateStream(Stream stream) {
        final Map defaultConfig = this.getDefaultEmailAlarmCallbackConfig();
        LOG.debug("Creating email alarm callback for stream <" + stream.getId() + ">");
        final AlarmCallbackConfiguration alarmCallbackConfiguration = alarmCallbackService.create(stream.getId(),
                CreateAlarmCallbackRequest.create(
                        EmailAlarmCallback.class.getCanonicalName(),
                        "Email Alert Notification",
                        defaultConfig
                ),
                "local:admin"
        );
        try {
            final String callbackId = this.alarmCallbackService.save(alarmCallbackConfiguration);
            LOG.debug("Successfully created email alarm callback <" + callbackId + "> for stream <" + stream.getId() + ">.");
            return Optional.of(callbackId);
        } catch (ValidationException e) {
            LOG.error("Unable to create email alarm callback for stream <" + stream.getId() + ">: ", e);
        }
        return Optional.empty();
    }

    @VisibleForTesting
    Map getDefaultEmailAlarmCallbackConfig() {
        final ConfigurationRequest configurationRequest = this.emailAlarmCallback.getRequestedConfiguration();

        return configurationRequest.getFields().entrySet()
                .stream()
                .collect(Collectors.toMap(Map.Entry::getKey, entry -> entry.getValue().getDefaultValue()));
    }

    @AutoValue
    @WithBeanGetter
    @JsonAutoDetect
    public static abstract class MigrationCompleted {
        private static final String FIELD_CALLBACK_IDS = "callback_ids";

        @JsonProperty(FIELD_CALLBACK_IDS)
        public abstract Map> callbackIds();

        @JsonCreator
        public static MigrationCompleted create(@JsonProperty(FIELD_CALLBACK_IDS) Map> callbackIds) {
            return new AutoValue_V20161125142400_EmailAlarmCallbackMigration_MigrationCompleted(callbackIds);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy