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

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

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

import com.fasterxml.jackson.databind.JsonNode;
import com.google.common.collect.ImmutableSet;
import org.graylog2.indexer.ElasticsearchException;
import org.graylog2.indexer.IndexSet;
import org.graylog2.indexer.MongoIndexSet;
import org.graylog2.indexer.cluster.Node;
import org.graylog2.indexer.indexset.IndexSetService;
import org.graylog2.indexer.indices.Indices;
import org.graylog2.storage.SearchVersion;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Nonnull;
import javax.inject.Inject;
import java.time.ZonedDateTime;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import static org.graylog2.storage.SearchVersion.Distribution.*;
import static org.graylog2.storage.SearchVersion.Distribution.OPENSEARCH;

public class V20170607164210_MigrateReopenedIndicesToAliases extends Migration {
    private static final Logger LOG = LoggerFactory.getLogger(V20170607164210_MigrateReopenedIndicesToAliases.class);
    private static final String REOPENED_INDEX_SETTING = "graylog2_reopened";

    private final Node node;
    private final IndexSetService indexSetService;
    private final MongoIndexSet.Factory mongoIndexSetFactory;
    private final Indices indices;
    private final ClusterState clusterState;

    public interface ClusterState {
        JsonNode getForIndices(Collection indices);
    }

    @Inject
    public V20170607164210_MigrateReopenedIndicesToAliases(Node node,
                                                           IndexSetService indexSetService,
                                                           MongoIndexSet.Factory mongoIndexSetFactory,
                                                           Indices indices,
                                                           ClusterState clusterState) {
        this.node = node;
        this.indexSetService = indexSetService;
        this.mongoIndexSetFactory = mongoIndexSetFactory;
        this.indices = indices;
        this.clusterState = clusterState;
    }

    @Override
    public ZonedDateTime createdAt() {
        return ZonedDateTime.parse("2017-06-07T16:42:10Z");
    }

    // Create aliases for legacy reopened indices.
    @Override
    public void upgrade() {
        this.indexSetService.findAll()
                .stream()
                .map(mongoIndexSetFactory::create)
                .flatMap(indexSet -> getReopenedIndices(indexSet).stream())
                .peek(indexName -> LOG.debug("Marking index {} to be reopened using alias.", indexName))
                .forEach(indices::markIndexReopened);
    }

    private Set getReopenedIndices(final Collection indices) {
        final SearchVersion elasticsearchVersion = node.getVersion().orElseThrow(() -> new ElasticsearchException("Unable to retrieve Elasticsearch version."));

        final JsonNode clusterStateJson = clusterState.getForIndices(indices);

        final JsonNode indicesJson = clusterStateJson.path("metadata").path("indices");

        final ImmutableSet.Builder reopenedIndices = ImmutableSet.builder();

        if (indicesJson.isMissingNode()) {
            LOG.error("Retrieved cluster state is invalid (no metadata.indices key).");
            LOG.debug("Received cluster state was: {}", clusterStateJson.toString());
            return Collections.emptySet();
        }

        for (Iterator> it = indicesJson.fields(); it.hasNext(); ) {
            final Map.Entry entry = it.next();
            final String indexName = entry.getKey();
            final JsonNode value = entry.getValue();

            final JsonNode indexSettings = value.path("settings");
            if (indexSettings.isMissingNode()) {
                LOG.error("Unable to retrieve index settings from metadata for index {} - skipping.", indexName);
                LOG.debug("Index metadata was: {}", value.toString());
                continue;
            }
            if (checkForReopened(indexSettings, elasticsearchVersion)) {
                LOG.debug("Adding {} to list of indices to be migrated.", indexName);
                reopenedIndices.add(indexName);
            }
        }

        return reopenedIndices.build();
    }

    private boolean checkForReopened(@Nonnull JsonNode indexSettings, SearchVersion searchVersion) {
        final JsonNode settings;
        if (searchVersion.satisfies(ELASTICSEARCH, ">=2.1.0 & <5.0.0")) {
            settings = indexSettings;
        } else if (searchVersion.satisfies(ELASTICSEARCH, "^5.0.0 | ^6.0.0 | ^7.0.0") ||
                searchVersion.satisfies(OPENSEARCH, "^1.0.0 | ^2.0.0")) {
            settings = indexSettings.path("archived");
        } else {
            throw new ElasticsearchException("Unsupported search version: " + searchVersion);
        }

        // if this is a missing node, asBoolean() returns false
        return settings.path("index").path(REOPENED_INDEX_SETTING).asBoolean();
    }

    private Set getReopenedIndices(final IndexSet indexSet) {
        return getReopenedIndices(Collections.singleton(indexSet.getIndexWildcard()));
    }
}





© 2015 - 2024 Weber Informatics LLC | Privacy Policy