mirror of
https://github.com/elastic/elasticsearch.git
synced 2025-06-28 09:28:55 -04:00
[8.x] Reconcile differences between Stateful and Stateless dot-prefix validation (#114946) (#115057)
* Reconcile differences between Stateful and Stateless dot-prefix validation (#114946)
This commit makes the dot prefix deprecation match the existing changes to validation for the SLO
and SLA UIs.
Relates to #112571
(cherry picked from commit 5bf446ea2e
)
* Update not to use getFirst
---------
Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
8678c6d6da
commit
e9072e9bc4
2 changed files with 137 additions and 4 deletions
|
@ -56,6 +56,7 @@ public abstract class DotPrefixValidator<RequestType> implements MappedActionFil
|
|||
*
|
||||
* .elastic-connectors-* is used by enterprise search
|
||||
* .ml-* is used by ML
|
||||
* .slo-observability-* is used by Observability
|
||||
*/
|
||||
private static Set<String> IGNORED_INDEX_NAMES = Set.of(
|
||||
".elastic-connectors-v1",
|
||||
|
@ -63,7 +64,11 @@ public abstract class DotPrefixValidator<RequestType> implements MappedActionFil
|
|||
".ml-state",
|
||||
".ml-anomalies-unrelated"
|
||||
);
|
||||
private static Set<Pattern> IGNORED_INDEX_PATTERNS = Set.of(Pattern.compile("\\.ml-state-\\d+"));
|
||||
private static Set<Pattern> IGNORED_INDEX_PATTERNS = Set.of(
|
||||
Pattern.compile("\\.ml-state-\\d+"),
|
||||
Pattern.compile("\\.slo-observability\\.sli-v\\d+.*"),
|
||||
Pattern.compile("\\.slo-observability\\.summary-v\\d+.*")
|
||||
);
|
||||
|
||||
DeprecationLogger deprecationLogger = DeprecationLogger.getLogger(DotPrefixValidator.class);
|
||||
|
||||
|
@ -99,10 +104,11 @@ public abstract class DotPrefixValidator<RequestType> implements MappedActionFil
|
|||
if (Strings.hasLength(index)) {
|
||||
char c = getFirstChar(index);
|
||||
if (c == '.') {
|
||||
if (IGNORED_INDEX_NAMES.contains(index)) {
|
||||
final String strippedName = stripDateMath(index);
|
||||
if (IGNORED_INDEX_NAMES.contains(strippedName)) {
|
||||
return;
|
||||
}
|
||||
if (IGNORED_INDEX_PATTERNS.stream().anyMatch(p -> p.matcher(index).matches())) {
|
||||
if (IGNORED_INDEX_PATTERNS.stream().anyMatch(p -> p.matcher(strippedName).matches())) {
|
||||
return;
|
||||
}
|
||||
deprecationLogger.warn(
|
||||
|
@ -132,7 +138,18 @@ public abstract class DotPrefixValidator<RequestType> implements MappedActionFil
|
|||
return c;
|
||||
}
|
||||
|
||||
private boolean isInternalRequest() {
|
||||
private static String stripDateMath(String index) {
|
||||
char c = index.charAt(0);
|
||||
if (c == '<') {
|
||||
assert index.charAt(index.length() - 1) == '>'
|
||||
: "expected index name with date math to start with < and end with >, how did this pass request validation? " + index;
|
||||
return index.substring(1, index.length() - 1);
|
||||
} else {
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isInternalRequest() {
|
||||
final String actionOrigin = threadContext.getTransient(ThreadContext.ACTION_ORIGIN_TRANSIENT_NAME);
|
||||
final boolean isSystemContext = threadContext.isSystemContext();
|
||||
final boolean isInternalOrigin = Optional.ofNullable(actionOrigin).map(Strings::hasText).orElse(false);
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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", the "GNU Affero General Public License v3.0 only", 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", the "GNU Affero General Public
|
||||
* License v3.0 only", or the "Server Side Public License, v 1".
|
||||
*/
|
||||
|
||||
package org.elasticsearch.validation;
|
||||
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.settings.ClusterSettings;
|
||||
import org.elasticsearch.common.settings.Setting;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.util.concurrent.ThreadContext;
|
||||
import org.elasticsearch.common.util.set.Sets;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class DotPrefixValidatorTests extends ESTestCase {
|
||||
private final OperatorValidator<?> opV = new OperatorValidator<>();
|
||||
private final NonOperatorValidator<?> nonOpV = new NonOperatorValidator<>();
|
||||
private static final Set<Setting<?>> settings;
|
||||
|
||||
private static ClusterService clusterService;
|
||||
private static ClusterSettings clusterSettings;
|
||||
|
||||
static {
|
||||
Set<Setting<?>> cSettings = new HashSet<>(ClusterSettings.BUILT_IN_CLUSTER_SETTINGS);
|
||||
cSettings.add(DotPrefixValidator.VALIDATE_DOT_PREFIXES);
|
||||
settings = cSettings;
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() {
|
||||
clusterService = mock(ClusterService.class);
|
||||
clusterSettings = new ClusterSettings(Settings.EMPTY, Sets.newHashSet(DotPrefixValidator.VALIDATE_DOT_PREFIXES));
|
||||
when(clusterService.getClusterSettings()).thenReturn(clusterSettings);
|
||||
when(clusterService.getSettings()).thenReturn(Settings.EMPTY);
|
||||
when(clusterService.threadPool()).thenReturn(mock(ThreadPool.class));
|
||||
}
|
||||
|
||||
public void testValidation() {
|
||||
|
||||
nonOpV.validateIndices(Set.of("regular"));
|
||||
opV.validateIndices(Set.of("regular"));
|
||||
assertFails(Set.of(".regular"));
|
||||
opV.validateIndices(Set.of(".regular"));
|
||||
assertFails(Set.of("first", ".second"));
|
||||
assertFails(Set.of("<.regular-{MM-yy-dd}>"));
|
||||
|
||||
// Test ignored names
|
||||
nonOpV.validateIndices(Set.of(".elastic-connectors-v1"));
|
||||
nonOpV.validateIndices(Set.of(".elastic-connectors-sync-jobs-v1"));
|
||||
nonOpV.validateIndices(Set.of(".ml-state"));
|
||||
nonOpV.validateIndices(Set.of(".ml-anomalies-unrelated"));
|
||||
|
||||
// Test ignored patterns
|
||||
nonOpV.validateIndices(Set.of(".ml-state-21309"));
|
||||
nonOpV.validateIndices(Set.of(">.ml-state-21309>"));
|
||||
nonOpV.validateIndices(Set.of(".slo-observability.sli-v2"));
|
||||
nonOpV.validateIndices(Set.of(".slo-observability.sli-v2.3"));
|
||||
nonOpV.validateIndices(Set.of(".slo-observability.sli-v2.3-2024-01-01"));
|
||||
nonOpV.validateIndices(Set.of("<.slo-observability.sli-v3.3.{2024-10-16||/M{yyyy-MM-dd|UTC}}>"));
|
||||
nonOpV.validateIndices(Set.of(".slo-observability.summary-v2"));
|
||||
nonOpV.validateIndices(Set.of(".slo-observability.summary-v2.3"));
|
||||
nonOpV.validateIndices(Set.of(".slo-observability.summary-v2.3-2024-01-01"));
|
||||
nonOpV.validateIndices(Set.of("<.slo-observability.summary-v3.3.{2024-10-16||/M{yyyy-MM-dd|UTC}}>"));
|
||||
}
|
||||
|
||||
private void assertFails(Set<String> indices) {
|
||||
nonOpV.validateIndices(indices);
|
||||
assertWarnings(
|
||||
"Index ["
|
||||
+ indices.stream().filter(i -> i.startsWith(".") || i.startsWith("<.")).toList().get(0)
|
||||
+ "] name begins with a dot (.), which is deprecated, and will not be allowed in a future Elasticsearch version."
|
||||
);
|
||||
}
|
||||
|
||||
private class NonOperatorValidator<R> extends DotPrefixValidator<R> {
|
||||
|
||||
private NonOperatorValidator() {
|
||||
super(new ThreadContext(Settings.EMPTY), clusterService);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<String> getIndicesFromRequest(Object request) {
|
||||
return Set.of();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String actionName() {
|
||||
return "";
|
||||
}
|
||||
|
||||
@Override
|
||||
boolean isInternalRequest() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private class OperatorValidator<R> extends NonOperatorValidator<R> {
|
||||
@Override
|
||||
boolean isInternalRequest() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue