org.elasticsearch.cluster.metadata.IndexAbstractionResolver Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of elasticsearch Show documentation
Show all versions of elasticsearch Show documentation
Elasticsearch subproject :server
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
package org.elasticsearch.cluster.metadata;
import org.elasticsearch.action.support.IndicesOptions;
import org.elasticsearch.common.regex.Regex;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.indices.SystemIndices.SystemIndexAccessLevel;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Predicate;
import java.util.function.Supplier;
public class IndexAbstractionResolver {
private final IndexNameExpressionResolver indexNameExpressionResolver;
public IndexAbstractionResolver(IndexNameExpressionResolver indexNameExpressionResolver) {
this.indexNameExpressionResolver = indexNameExpressionResolver;
}
public List resolveIndexAbstractions(
Iterable indices,
IndicesOptions indicesOptions,
Metadata metadata,
Supplier> allAuthorizedAndAvailable,
Predicate isAuthorized,
boolean includeDataStreams
) {
List finalIndices = new ArrayList<>();
boolean wildcardSeen = false;
for (String index : indices) {
String indexAbstraction;
boolean minus = false;
if (index.charAt(0) == '-' && wildcardSeen) {
indexAbstraction = index.substring(1);
minus = true;
} else {
indexAbstraction = index;
}
// we always need to check for date math expressions
indexAbstraction = IndexNameExpressionResolver.resolveDateMathExpression(indexAbstraction);
if (indicesOptions.expandWildcardExpressions() && Regex.isSimpleMatchPattern(indexAbstraction)) {
wildcardSeen = true;
Set resolvedIndices = new HashSet<>();
for (String authorizedIndex : allAuthorizedAndAvailable.get()) {
if (Regex.simpleMatch(indexAbstraction, authorizedIndex)
&& isIndexVisible(
indexAbstraction,
authorizedIndex,
indicesOptions,
metadata,
indexNameExpressionResolver,
includeDataStreams
)) {
resolvedIndices.add(authorizedIndex);
}
}
if (resolvedIndices.isEmpty()) {
// es core honours allow_no_indices for each wildcard expression, we do the same here by throwing index not found.
if (indicesOptions.allowNoIndices() == false) {
throw new IndexNotFoundException(indexAbstraction);
}
} else {
if (minus) {
finalIndices.removeAll(resolvedIndices);
} else {
finalIndices.addAll(resolvedIndices);
}
}
} else {
if (minus) {
finalIndices.remove(indexAbstraction);
} else if (indicesOptions.ignoreUnavailable() == false || isAuthorized.test(indexAbstraction)) {
// Unauthorized names are considered unavailable, so if `ignoreUnavailable` is `true` they should be silently
// discarded from the `finalIndices` list. Other "ways of unavailable" must be handled by the action
// handler, see: https://github.com/elastic/elasticsearch/issues/90215
finalIndices.add(indexAbstraction);
}
}
}
return finalIndices;
}
public static boolean isIndexVisible(
String expression,
String index,
IndicesOptions indicesOptions,
Metadata metadata,
IndexNameExpressionResolver resolver,
boolean includeDataStreams
) {
IndexAbstraction indexAbstraction = metadata.getIndicesLookup().get(index);
if (indexAbstraction == null) {
throw new IllegalStateException("could not resolve index abstraction [" + index + "]");
}
final boolean isHidden = indexAbstraction.isHidden();
boolean isVisible = isHidden == false || indicesOptions.expandWildcardsHidden() || isVisibleDueToImplicitHidden(expression, index);
if (indexAbstraction.getType() == IndexAbstraction.Type.ALIAS) {
// it's an alias, ignore expandWildcardsOpen and expandWildcardsClosed.
// complicated to support those options with aliases pointing to multiple indices...
return isVisible && indicesOptions.ignoreAliases() == false;
}
if (indexAbstraction.getType() == IndexAbstraction.Type.DATA_STREAM) {
if (includeDataStreams == false) {
return false;
}
if (indexAbstraction.isSystem()) {
return isSystemIndexVisible(resolver, indexAbstraction);
} else {
return isVisible;
}
}
assert indexAbstraction.getIndices().size() == 1 : "concrete index must point to a single index";
if (isVisible == false) {
return false;
}
if (indexAbstraction.isSystem()) {
// check if it is net new
if (resolver.getNetNewSystemIndexPredicate().test(indexAbstraction.getName())) {
return isSystemIndexVisible(resolver, indexAbstraction);
}
// does the system index back a system data stream?
if (indexAbstraction.getParentDataStream() != null) {
if (indexAbstraction.getParentDataStream().isSystem() == false) {
assert false : "system index is part of a data stream that is not a system data stream";
throw new IllegalStateException("system index is part of a data stream that is not a system data stream");
}
return isSystemIndexVisible(resolver, indexAbstraction);
}
}
IndexMetadata indexMetadata = metadata.index(indexAbstraction.getIndices().get(0));
if (indexMetadata.getState() == IndexMetadata.State.CLOSE && indicesOptions.expandWildcardsClosed()) {
return true;
}
if (indexMetadata.getState() == IndexMetadata.State.OPEN && indicesOptions.expandWildcardsOpen()) {
return true;
}
return false;
}
private static boolean isSystemIndexVisible(IndexNameExpressionResolver resolver, IndexAbstraction indexAbstraction) {
final SystemIndexAccessLevel level = resolver.getSystemIndexAccessLevel();
switch (level) {
case ALL:
return true;
case NONE:
return false;
case RESTRICTED:
return resolver.getSystemIndexAccessPredicate().test(indexAbstraction.getName());
case BACKWARDS_COMPATIBLE_ONLY:
return resolver.getNetNewSystemIndexPredicate().test(indexAbstraction.getName());
default:
assert false : "unexpected system index access level [" + level + "]";
throw new IllegalStateException("unexpected system index access level [" + level + "]");
}
}
private static boolean isVisibleDueToImplicitHidden(String expression, String index) {
return index.startsWith(".") && expression.startsWith(".") && Regex.isSimpleMatchPattern(expression);
}
}