|
@@ -53,6 +53,7 @@ import org.elasticsearch.common.UUIDs;
|
|
|
import org.elasticsearch.common.ValidationException;
|
|
|
import org.elasticsearch.common.compress.CompressedXContent;
|
|
|
import org.elasticsearch.common.io.PathUtils;
|
|
|
+import org.elasticsearch.common.logging.DeprecationLogger;
|
|
|
import org.elasticsearch.common.settings.IndexScopedSettings;
|
|
|
import org.elasticsearch.common.settings.Setting;
|
|
|
import org.elasticsearch.common.settings.Settings;
|
|
@@ -70,6 +71,7 @@ import org.elasticsearch.index.query.QueryShardContext;
|
|
|
import org.elasticsearch.indices.IndexCreationException;
|
|
|
import org.elasticsearch.indices.IndicesService;
|
|
|
import org.elasticsearch.indices.InvalidIndexNameException;
|
|
|
+import org.elasticsearch.indices.SystemIndexDescriptor;
|
|
|
import org.elasticsearch.indices.cluster.IndicesClusterStateService.AllocatedIndices.IndexRemovalReason;
|
|
|
import org.elasticsearch.threadpool.ThreadPool;
|
|
|
|
|
@@ -78,6 +80,7 @@ import java.io.UnsupportedEncodingException;
|
|
|
import java.nio.file.Path;
|
|
|
import java.time.Instant;
|
|
|
import java.util.ArrayList;
|
|
|
+import java.util.Collection;
|
|
|
import java.util.Collections;
|
|
|
import java.util.HashMap;
|
|
|
import java.util.List;
|
|
@@ -89,6 +92,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|
|
import java.util.function.BiFunction;
|
|
|
import java.util.function.Predicate;
|
|
|
import java.util.function.Supplier;
|
|
|
+import java.util.stream.Collectors;
|
|
|
import java.util.stream.IntStream;
|
|
|
|
|
|
import static java.util.stream.Collectors.toList;
|
|
@@ -103,6 +107,7 @@ import static org.elasticsearch.cluster.metadata.IndexMetaData.SETTING_NUMBER_OF
|
|
|
*/
|
|
|
public class MetaDataCreateIndexService {
|
|
|
private static final Logger logger = LogManager.getLogger(MetaDataCreateIndexService.class);
|
|
|
+ private static final DeprecationLogger deprecationLogger = new DeprecationLogger(logger);
|
|
|
|
|
|
public static final int MAX_INDEX_NAME_BYTES = 255;
|
|
|
|
|
@@ -115,19 +120,21 @@ public class MetaDataCreateIndexService {
|
|
|
private final IndexScopedSettings indexScopedSettings;
|
|
|
private final ActiveShardsObserver activeShardsObserver;
|
|
|
private final NamedXContentRegistry xContentRegistry;
|
|
|
+ private final Collection<SystemIndexDescriptor> systemIndexDescriptors;
|
|
|
private final boolean forbidPrivateIndexSettings;
|
|
|
|
|
|
public MetaDataCreateIndexService(
|
|
|
- final Settings settings,
|
|
|
- final ClusterService clusterService,
|
|
|
- final IndicesService indicesService,
|
|
|
- final AllocationService allocationService,
|
|
|
- final AliasValidator aliasValidator,
|
|
|
- final Environment env,
|
|
|
- final IndexScopedSettings indexScopedSettings,
|
|
|
- final ThreadPool threadPool,
|
|
|
- final NamedXContentRegistry xContentRegistry,
|
|
|
- final boolean forbidPrivateIndexSettings) {
|
|
|
+ final Settings settings,
|
|
|
+ final ClusterService clusterService,
|
|
|
+ final IndicesService indicesService,
|
|
|
+ final AllocationService allocationService,
|
|
|
+ final AliasValidator aliasValidator,
|
|
|
+ final Environment env,
|
|
|
+ final IndexScopedSettings indexScopedSettings,
|
|
|
+ final ThreadPool threadPool,
|
|
|
+ final NamedXContentRegistry xContentRegistry,
|
|
|
+ final Collection<SystemIndexDescriptor> systemIndexDescriptors,
|
|
|
+ final boolean forbidPrivateIndexSettings) {
|
|
|
this.settings = settings;
|
|
|
this.clusterService = clusterService;
|
|
|
this.indicesService = indicesService;
|
|
@@ -137,17 +144,40 @@ public class MetaDataCreateIndexService {
|
|
|
this.indexScopedSettings = indexScopedSettings;
|
|
|
this.activeShardsObserver = new ActiveShardsObserver(clusterService, threadPool);
|
|
|
this.xContentRegistry = xContentRegistry;
|
|
|
+ this.systemIndexDescriptors = systemIndexDescriptors;
|
|
|
this.forbidPrivateIndexSettings = forbidPrivateIndexSettings;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Validate the name for an index against some static rules and a cluster state.
|
|
|
*/
|
|
|
- public static void validateIndexName(String index, ClusterState state) {
|
|
|
+ public void validateIndexName(String index, ClusterState state, @Nullable Boolean isHidden) {
|
|
|
validateIndexOrAliasName(index, InvalidIndexNameException::new);
|
|
|
if (!index.toLowerCase(Locale.ROOT).equals(index)) {
|
|
|
throw new InvalidIndexNameException(index, "must be lowercase");
|
|
|
}
|
|
|
+
|
|
|
+ if (index.charAt(0) == '.') {
|
|
|
+ List<SystemIndexDescriptor> matchingDescriptors = systemIndexDescriptors.stream()
|
|
|
+ .filter(descriptor -> descriptor.matchesIndexPattern(index))
|
|
|
+ .collect(toList());
|
|
|
+ if (matchingDescriptors.isEmpty() && (isHidden == null || isHidden == Boolean.FALSE)) {
|
|
|
+ deprecationLogger.deprecated("index name [{}] starts with a dot '.', in the next major version, index names " +
|
|
|
+ "starting with a dot are reserved for hidden indices and system indices", index);
|
|
|
+ } else if (matchingDescriptors.size() > 1) {
|
|
|
+ // This should be prevented by erroring on overlapping patterns at startup time, but is here just in case.
|
|
|
+ StringBuilder errorMessage = new StringBuilder()
|
|
|
+ .append("index name [")
|
|
|
+ .append(index)
|
|
|
+ .append("] is claimed as a system index by multiple system index patterns: [")
|
|
|
+ .append(matchingDescriptors.stream()
|
|
|
+ .map(descriptor -> "pattern: [" + descriptor.getIndexPattern() +
|
|
|
+ "], description: [" + descriptor.getDescription() + "]").collect(Collectors.joining("; ")));
|
|
|
+ // Throw AssertionError if assertions are enabled, or a regular exception otherwise:
|
|
|
+ assert false : errorMessage.toString();
|
|
|
+ throw new IllegalStateException(errorMessage.toString());
|
|
|
+ }
|
|
|
+ }
|
|
|
if (state.routingTable().hasIndex(index)) {
|
|
|
throw new ResourceAlreadyExistsException(state.routingTable().index(index).getIndex());
|
|
|
}
|
|
@@ -653,7 +683,8 @@ public class MetaDataCreateIndexService {
|
|
|
}
|
|
|
|
|
|
private void validate(CreateIndexClusterStateUpdateRequest request, ClusterState state) {
|
|
|
- validateIndexName(request.index(), state);
|
|
|
+ boolean isHidden = IndexMetaData.INDEX_HIDDEN_SETTING.get(request.settings());
|
|
|
+ validateIndexName(request.index(), state, isHidden);
|
|
|
validateIndexSettings(request.index(), request.settings(), forbidPrivateIndexSettings);
|
|
|
}
|
|
|
|