Refactor put mapping request validation for reuse (#43005)
This commit refactors put mapping request validation for reuse. The concrete case that we are after here is the ability to apply effectively the same framework to indices aliases requests. This commit refactors the put mapping request validation framework to allow for that.
This commit is contained in:
parent
0a982fc57f
commit
915d2f2daa
|
@ -118,6 +118,7 @@ import org.elasticsearch.action.admin.indices.mapping.get.TransportGetFieldMappi
|
|||
import org.elasticsearch.action.admin.indices.mapping.get.TransportGetFieldMappingsIndexAction;
|
||||
import org.elasticsearch.action.admin.indices.mapping.get.TransportGetMappingsAction;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingAction;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.TransportPutMappingAction;
|
||||
import org.elasticsearch.action.admin.indices.open.OpenIndexAction;
|
||||
import org.elasticsearch.action.admin.indices.open.TransportOpenIndexAction;
|
||||
|
@ -204,6 +205,7 @@ import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
|||
import org.elasticsearch.cluster.node.DiscoveryNodes;
|
||||
import org.elasticsearch.common.NamedRegistry;
|
||||
import org.elasticsearch.common.inject.AbstractModule;
|
||||
import org.elasticsearch.common.inject.TypeLiteral;
|
||||
import org.elasticsearch.common.inject.multibindings.MapBinder;
|
||||
import org.elasticsearch.common.settings.ClusterSettings;
|
||||
import org.elasticsearch.common.settings.IndexScopedSettings;
|
||||
|
@ -359,7 +361,7 @@ public class ActionModule extends AbstractModule {
|
|||
private final AutoCreateIndex autoCreateIndex;
|
||||
private final DestructiveOperations destructiveOperations;
|
||||
private final RestController restController;
|
||||
private final TransportPutMappingAction.RequestValidators mappingRequestValidators;
|
||||
private final RequestValidators<PutMappingRequest> mappingRequestValidators;
|
||||
|
||||
public ActionModule(boolean transportClient, Settings settings, IndexNameExpressionResolver indexNameExpressionResolver,
|
||||
IndexScopedSettings indexScopedSettings, ClusterSettings clusterSettings, SettingsFilter settingsFilter,
|
||||
|
@ -391,9 +393,8 @@ public class ActionModule extends AbstractModule {
|
|||
restWrapper = newRestWrapper;
|
||||
}
|
||||
}
|
||||
mappingRequestValidators = new TransportPutMappingAction.RequestValidators(
|
||||
actionPlugins.stream().flatMap(p -> p.mappingRequestValidators().stream()).collect(Collectors.toList())
|
||||
);
|
||||
mappingRequestValidators = new RequestValidators<>(
|
||||
actionPlugins.stream().flatMap(p -> p.mappingRequestValidators().stream()).collect(Collectors.toList()));
|
||||
|
||||
if (transportClient) {
|
||||
restController = null;
|
||||
|
@ -690,7 +691,7 @@ public class ActionModule extends AbstractModule {
|
|||
protected void configure() {
|
||||
bind(ActionFilters.class).toInstance(actionFilters);
|
||||
bind(DestructiveOperations.class).toInstance(destructiveOperations);
|
||||
bind(TransportPutMappingAction.RequestValidators.class).toInstance(mappingRequestValidators);
|
||||
bind(new TypeLiteral<RequestValidators<PutMappingRequest>>() {}).toInstance(mappingRequestValidators);
|
||||
|
||||
if (false == transportClient) {
|
||||
// Supporting classes only used when not a transport client
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.action;
|
||||
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.index.Index;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
|
||||
public class RequestValidators<T extends ActionRequest> {
|
||||
|
||||
private final Collection<RequestValidator<T>> validators;
|
||||
|
||||
public RequestValidators(Collection<RequestValidator<T>> validators) {
|
||||
this.validators = validators;
|
||||
}
|
||||
|
||||
public Optional<Exception> validateRequest(final T request, final ClusterState state, final Index[] indices) {
|
||||
Exception exception = null;
|
||||
for (final RequestValidator<T> validator : validators) {
|
||||
final Optional<Exception> maybeException = validator.validateRequest(request, state, indices);
|
||||
if (maybeException.isPresent() == false) continue;
|
||||
if (exception == null) {
|
||||
exception = maybeException.get();
|
||||
} else {
|
||||
exception.addSuppressed(maybeException.get());
|
||||
}
|
||||
}
|
||||
return Optional.ofNullable(exception);
|
||||
}
|
||||
|
||||
/**
|
||||
* A validator that validates an request associated with indices before executing it.
|
||||
*/
|
||||
public interface RequestValidator<T extends ActionRequest> {
|
||||
|
||||
/**
|
||||
* Validates a given request with its associated concrete indices and the current state.
|
||||
*
|
||||
* @param request the request to validate
|
||||
* @param state the current cluster state
|
||||
* @param indices the concrete indices that associated with the given request
|
||||
* @return an optional exception indicates a reason that the given request should be aborted, otherwise empty
|
||||
*/
|
||||
Optional<Exception> validateRequest(T request, ClusterState state, Index[] indices);
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.action.admin.indices.mapping.put;
|
||||
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.index.Index;
|
||||
|
||||
/**
|
||||
* A validator that validates a {@link PutMappingRequest} before executing it.
|
||||
* @see TransportPutMappingAction.RequestValidators
|
||||
*/
|
||||
public interface MappingRequestValidator {
|
||||
|
||||
/**
|
||||
* Validates a given put mapping request with its associated concrete indices and the current state.
|
||||
*
|
||||
* @param request the request to validate
|
||||
* @param state the current cluster state
|
||||
* @param indices the concrete indices that associated with the given put mapping request
|
||||
* @return a non-null exception indicates a reason that the given request should be aborted; otherwise returns null.
|
||||
*/
|
||||
Exception validateRequest(PutMappingRequest request, ClusterState state, Index[] indices);
|
||||
}
|
|
@ -21,6 +21,7 @@ package org.elasticsearch.action.admin.indices.mapping.put;
|
|||
|
||||
import org.apache.logging.log4j.message.ParameterizedMessage;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.RequestValidators;
|
||||
import org.elasticsearch.action.support.ActionFilters;
|
||||
import org.elasticsearch.action.support.master.AcknowledgedResponse;
|
||||
import org.elasticsearch.action.support.master.TransportMasterNodeAction;
|
||||
|
@ -37,7 +38,8 @@ import org.elasticsearch.index.IndexNotFoundException;
|
|||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.transport.TransportService;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Put mapping action.
|
||||
|
@ -45,17 +47,21 @@ import java.util.Collection;
|
|||
public class TransportPutMappingAction extends TransportMasterNodeAction<PutMappingRequest, AcknowledgedResponse> {
|
||||
|
||||
private final MetaDataMappingService metaDataMappingService;
|
||||
private final RequestValidators requestValidators;
|
||||
private final RequestValidators<PutMappingRequest> requestValidators;
|
||||
|
||||
@Inject
|
||||
public TransportPutMappingAction(TransportService transportService, ClusterService clusterService,
|
||||
ThreadPool threadPool, MetaDataMappingService metaDataMappingService,
|
||||
ActionFilters actionFilters, IndexNameExpressionResolver indexNameExpressionResolver,
|
||||
RequestValidators requestValidators) {
|
||||
public TransportPutMappingAction(
|
||||
final TransportService transportService,
|
||||
final ClusterService clusterService,
|
||||
final ThreadPool threadPool,
|
||||
final MetaDataMappingService metaDataMappingService,
|
||||
final ActionFilters actionFilters,
|
||||
final IndexNameExpressionResolver indexNameExpressionResolver,
|
||||
final RequestValidators<PutMappingRequest> requestValidators) {
|
||||
super(PutMappingAction.NAME, transportService, clusterService, threadPool, actionFilters, indexNameExpressionResolver,
|
||||
PutMappingRequest::new);
|
||||
this.metaDataMappingService = metaDataMappingService;
|
||||
this.requestValidators = requestValidators;
|
||||
this.requestValidators = Objects.requireNonNull(requestValidators);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -87,9 +93,9 @@ public class TransportPutMappingAction extends TransportMasterNodeAction<PutMapp
|
|||
final Index[] concreteIndices = request.getConcreteIndex() == null ?
|
||||
indexNameExpressionResolver.concreteIndices(state, request)
|
||||
: new Index[] {request.getConcreteIndex()};
|
||||
final Exception validationException = requestValidators.validateRequest(request, state, concreteIndices);
|
||||
if (validationException != null) {
|
||||
listener.onFailure(validationException);
|
||||
final Optional<Exception> maybeValidationException = requestValidators.validateRequest(request, state, concreteIndices);
|
||||
if (maybeValidationException.isPresent()) {
|
||||
listener.onFailure(maybeValidationException.get());
|
||||
return;
|
||||
}
|
||||
PutMappingClusterStateUpdateRequest updateRequest = new PutMappingClusterStateUpdateRequest()
|
||||
|
@ -118,26 +124,4 @@ public class TransportPutMappingAction extends TransportMasterNodeAction<PutMapp
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public static class RequestValidators {
|
||||
private final Collection<MappingRequestValidator> validators;
|
||||
|
||||
public RequestValidators(Collection<MappingRequestValidator> validators) {
|
||||
this.validators = validators;
|
||||
}
|
||||
|
||||
Exception validateRequest(PutMappingRequest request, ClusterState state, Index[] indices) {
|
||||
Exception firstException = null;
|
||||
for (MappingRequestValidator validator : validators) {
|
||||
final Exception e = validator.validateRequest(request, state, indices);
|
||||
if (e == null) continue;
|
||||
if (firstException == null) {
|
||||
firstException = e;
|
||||
} else {
|
||||
firstException.addSuppressed(e);
|
||||
}
|
||||
}
|
||||
return firstException;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,8 +22,8 @@ package org.elasticsearch.plugins;
|
|||
import org.elasticsearch.action.Action;
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.MappingRequestValidator;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.TransportPutMappingAction;
|
||||
import org.elasticsearch.action.RequestValidators;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.action.support.ActionFilter;
|
||||
import org.elasticsearch.action.support.TransportAction;
|
||||
import org.elasticsearch.action.support.TransportActions;
|
||||
|
@ -183,10 +183,11 @@ public interface ActionPlugin {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a collection of validators that are used by {@link TransportPutMappingAction.RequestValidators} to
|
||||
* validate a {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} before the executing it.
|
||||
* Returns a collection of validators that are used by {@link RequestValidators} to validate a
|
||||
* {@link org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest} before the executing it.
|
||||
*/
|
||||
default Collection<MappingRequestValidator> mappingRequestValidators() {
|
||||
default Collection<RequestValidators.RequestValidator<PutMappingRequest>> mappingRequestValidators() {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.action;
|
||||
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.common.Randomness;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.test.hamcrest.OptionalMatchers;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class RequestValidatorsTests extends ESTestCase {
|
||||
|
||||
private final RequestValidators.RequestValidator<PutMappingRequest> EMPTY = (request, state, indices) -> Optional.empty();
|
||||
private final RequestValidators.RequestValidator<PutMappingRequest> FAIL =
|
||||
(request, state, indices) -> Optional.of(new Exception("failure"));
|
||||
|
||||
public void testValidates() {
|
||||
final int numberOfValidations = randomIntBetween(0, 8);
|
||||
final List<RequestValidators.RequestValidator<PutMappingRequest>> validators = new ArrayList<>(numberOfValidations);
|
||||
for (int i = 0; i < numberOfValidations; i++) {
|
||||
validators.add(EMPTY);
|
||||
}
|
||||
final RequestValidators<PutMappingRequest> requestValidators = new RequestValidators<>(validators);
|
||||
assertThat(requestValidators.validateRequest(null, null, null), OptionalMatchers.isEmpty());
|
||||
}
|
||||
|
||||
public void testFailure() {
|
||||
final RequestValidators<PutMappingRequest> validators = new RequestValidators<>(Collections.singletonList(FAIL));
|
||||
assertThat(validators.validateRequest(null, null, null), OptionalMatchers.isPresent());
|
||||
}
|
||||
|
||||
public void testValidatesAfterFailure() {
|
||||
final RequestValidators<PutMappingRequest> validators =
|
||||
new RequestValidators<>(Collections.unmodifiableList(Arrays.asList(FAIL, EMPTY)));
|
||||
assertThat(validators.validateRequest(null, null, null), OptionalMatchers.isPresent());
|
||||
}
|
||||
|
||||
public void testMultipleFailures() {
|
||||
final int numberOfFailures = randomIntBetween(2, 8);
|
||||
final List<RequestValidators.RequestValidator<PutMappingRequest>> validators = new ArrayList<>(numberOfFailures);
|
||||
for (int i = 0; i < numberOfFailures; i++) {
|
||||
validators.add(FAIL);
|
||||
}
|
||||
final RequestValidators<PutMappingRequest> requestValidators = new RequestValidators<>(validators);
|
||||
final Optional<Exception> e = requestValidators.validateRequest(null, null, null);
|
||||
assertThat(e, OptionalMatchers.isPresent());
|
||||
// noinspection OptionalGetWithoutIsPresent
|
||||
assertThat(e.get().getSuppressed(), Matchers.arrayWithSize(numberOfFailures - 1));
|
||||
}
|
||||
|
||||
public void testRandom() {
|
||||
final int numberOfValidations = randomIntBetween(0, 8);
|
||||
final int numberOfFailures = randomIntBetween(0, 8);
|
||||
final List<RequestValidators.RequestValidator<PutMappingRequest>> validators =
|
||||
new ArrayList<>(numberOfValidations + numberOfFailures);
|
||||
for (int i = 0; i < numberOfValidations; i++) {
|
||||
validators.add(EMPTY);
|
||||
}
|
||||
for (int i = 0; i < numberOfFailures; i++) {
|
||||
validators.add(FAIL);
|
||||
}
|
||||
Randomness.shuffle(validators);
|
||||
final RequestValidators<PutMappingRequest> requestValidators = new RequestValidators<>(validators);
|
||||
final Optional<Exception> e = requestValidators.validateRequest(null, null, null);
|
||||
if (numberOfFailures == 0) {
|
||||
assertThat(e, OptionalMatchers.isEmpty());
|
||||
} else {
|
||||
assertThat(e, OptionalMatchers.isPresent());
|
||||
// noinspection OptionalGetWithoutIsPresent
|
||||
assertThat(e.get().getSuppressed(), Matchers.arrayWithSize(numberOfFailures - 1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.action.admin.indices.mapping.put;
|
||||
|
||||
import org.elasticsearch.common.Randomness;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.hamcrest.Matchers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class TransportPutMappingRequestValidatorsTests extends ESTestCase {
|
||||
|
||||
private final MappingRequestValidator EMPTY = (request, state, indices) -> null;
|
||||
private final MappingRequestValidator FAIL = (request, state, indices) -> new Exception("failure");
|
||||
|
||||
public void testValidates() {
|
||||
final int numberOfValidations = randomIntBetween(0, 8);
|
||||
final List<MappingRequestValidator> validators = new ArrayList<>(numberOfValidations);
|
||||
for (int i = 0; i < numberOfValidations; i++) {
|
||||
validators.add(EMPTY);
|
||||
}
|
||||
final TransportPutMappingAction.RequestValidators requestValidators = new TransportPutMappingAction.RequestValidators(validators);
|
||||
assertNull(requestValidators.validateRequest(null, null, null));
|
||||
}
|
||||
|
||||
public void testFailure() {
|
||||
final TransportPutMappingAction.RequestValidators validators =
|
||||
new TransportPutMappingAction.RequestValidators(Collections.singletonList(FAIL));
|
||||
assertNotNull(validators.validateRequest(null, null, null));
|
||||
}
|
||||
|
||||
public void testValidatesAfterFailure() {
|
||||
final TransportPutMappingAction.RequestValidators validators =
|
||||
new TransportPutMappingAction.RequestValidators(Collections.unmodifiableList(Arrays.asList(FAIL, EMPTY)));
|
||||
assertNotNull(validators.validateRequest(null, null, null));
|
||||
}
|
||||
|
||||
public void testMultipleFailures() {
|
||||
final int numberOfFailures = randomIntBetween(2, 8);
|
||||
final List<MappingRequestValidator> validators = new ArrayList<>(numberOfFailures);
|
||||
for (int i = 0; i < numberOfFailures; i++) {
|
||||
validators.add(FAIL);
|
||||
}
|
||||
final TransportPutMappingAction.RequestValidators requestValidators = new TransportPutMappingAction.RequestValidators(validators);
|
||||
final Exception e = requestValidators.validateRequest(null, null, null);
|
||||
assertNotNull(e);
|
||||
assertThat(e.getSuppressed(), Matchers.arrayWithSize(numberOfFailures - 1));
|
||||
}
|
||||
|
||||
public void testRandom() {
|
||||
final int numberOfValidations = randomIntBetween(0, 8);
|
||||
final int numberOfFailures = randomIntBetween(0, 8);
|
||||
final List<MappingRequestValidator> validators = new ArrayList<>(numberOfValidations + numberOfFailures);
|
||||
for (int i = 0; i < numberOfValidations; i++) {
|
||||
validators.add(EMPTY);
|
||||
}
|
||||
for (int i = 0; i < numberOfFailures; i++) {
|
||||
validators.add(FAIL);
|
||||
}
|
||||
Randomness.shuffle(validators);
|
||||
final TransportPutMappingAction.RequestValidators requestValidators = new TransportPutMappingAction.RequestValidators(validators);
|
||||
final Exception e = requestValidators.validateRequest(null, null, null);
|
||||
if (numberOfFailures == 0) {
|
||||
assertNull(e);
|
||||
} else {
|
||||
assertNotNull(e);
|
||||
assertThat(e.getSuppressed(), Matchers.arrayWithSize(numberOfFailures - 1));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
package org.elasticsearch.action.admin.indices.mapping.put;
|
||||
|
||||
import org.elasticsearch.action.RequestValidators;
|
||||
import org.elasticsearch.common.util.concurrent.ConcurrentCollections;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.plugins.ActionPlugin;
|
||||
|
@ -29,6 +30,7 @@ import java.util.Arrays;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -38,14 +40,15 @@ public class ValidateMappingRequestPluginIT extends ESSingleNodeTestCase {
|
|||
static final Map<String, Collection<String>> allowedOrigins = ConcurrentCollections.newConcurrentMap();
|
||||
public static class TestPlugin extends Plugin implements ActionPlugin {
|
||||
@Override
|
||||
public Collection<MappingRequestValidator> mappingRequestValidators() {
|
||||
public Collection<RequestValidators.RequestValidator<PutMappingRequest>> mappingRequestValidators() {
|
||||
return Collections.singletonList((request, state, indices) -> {
|
||||
for (Index index : indices) {
|
||||
if (allowedOrigins.getOrDefault(index.getName(), Collections.emptySet()).contains(request.origin()) == false) {
|
||||
return new IllegalStateException("not allowed: index[" + index.getName() + "] origin[" + request.origin() + "]");
|
||||
return Optional.of(
|
||||
new IllegalStateException("not allowed: index[" + index.getName() + "] origin[" + request.origin() + "]"));
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return Optional.empty();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.apache.logging.log4j.Logger;
|
|||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.Action;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.RequestValidators;
|
||||
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryAction;
|
||||
import org.elasticsearch.action.admin.cluster.repositories.put.TransportPutRepositoryAction;
|
||||
import org.elasticsearch.action.admin.cluster.reroute.ClusterRerouteAction;
|
||||
|
@ -1154,7 +1155,7 @@ public class SnapshotResiliencyTests extends ESTestCase {
|
|||
);
|
||||
actions.put(PutMappingAction.INSTANCE,
|
||||
new TransportPutMappingAction(transportService, clusterService, threadPool, metaDataMappingService,
|
||||
actionFilters, indexNameExpressionResolver, new TransportPutMappingAction.RequestValidators(Collections.emptyList())));
|
||||
actionFilters, indexNameExpressionResolver, new RequestValidators<>(Collections.emptyList())));
|
||||
final ResponseCollectorService responseCollectorService = new ResponseCollectorService(clusterService);
|
||||
final SearchTransportService searchTransportService = new SearchTransportService(transportService,
|
||||
SearchExecutionStatsCollector.makeWrapper(responseCollectorService));
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.test.hamcrest;
|
||||
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public class OptionalMatchers {
|
||||
|
||||
private static class IsEmptyMatcher extends TypeSafeMatcher<Optional<?>> {
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(final Optional<?> item) {
|
||||
// noinspection OptionalAssignedToNull
|
||||
return item != null && item.isPresent() == false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(final Description description) {
|
||||
description.appendText("expected empty optional");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void describeMismatchSafely(final Optional<?> item, final Description mismatchDescription) {
|
||||
if (item == null) {
|
||||
mismatchDescription.appendText("was null");
|
||||
} else {
|
||||
mismatchDescription.appendText("was ").appendText(item.toString());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static IsEmptyMatcher isEmpty() {
|
||||
return new IsEmptyMatcher();
|
||||
}
|
||||
|
||||
private static class IsPresentMatcher extends TypeSafeMatcher<Optional<?>> {
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(final Optional<?> item) {
|
||||
return item != null && item.isPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(final Description description) {
|
||||
description.appendText("expected non-empty optional");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void describeMismatchSafely(final Optional<?> item, final Description mismatchDescription) {
|
||||
if (item == null) {
|
||||
mismatchDescription.appendText("was null");
|
||||
} else {
|
||||
mismatchDescription.appendText("was empty");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static IsPresentMatcher isPresent() {
|
||||
return new IsPresentMatcher();
|
||||
}
|
||||
|
||||
}
|
|
@ -9,7 +9,8 @@ package org.elasticsearch.xpack.ccr;
|
|||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.MappingRequestValidator;
|
||||
import org.elasticsearch.action.RequestValidators;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
|
@ -350,7 +351,7 @@ public class Ccr extends Plugin implements ActionPlugin, PersistentTaskPlugin, E
|
|||
protected XPackLicenseState getLicenseState() { return XPackPlugin.getSharedLicenseState(); }
|
||||
|
||||
@Override
|
||||
public Collection<MappingRequestValidator> mappingRequestValidators() {
|
||||
public Collection<RequestValidators.RequestValidator<PutMappingRequest>> mappingRequestValidators() {
|
||||
return Collections.singletonList(CcrRequests.CCR_PUT_MAPPING_REQUEST_VALIDATOR);
|
||||
}
|
||||
|
||||
|
|
|
@ -7,9 +7,9 @@ package org.elasticsearch.xpack.ccr.action;
|
|||
|
||||
import org.elasticsearch.ElasticsearchStatusException;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.RequestValidators;
|
||||
import org.elasticsearch.action.admin.cluster.state.ClusterStateRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.MappingRequestValidator;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MappingMetaData;
|
||||
|
@ -22,6 +22,7 @@ import org.elasticsearch.xpack.ccr.CcrSettings;
|
|||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
|
@ -85,9 +86,10 @@ public final class CcrRequests {
|
|||
));
|
||||
}
|
||||
|
||||
public static final MappingRequestValidator CCR_PUT_MAPPING_REQUEST_VALIDATOR = (request, state, indices) -> {
|
||||
public static final RequestValidators.RequestValidator<PutMappingRequest> CCR_PUT_MAPPING_REQUEST_VALIDATOR =
|
||||
(request, state, indices) -> {
|
||||
if (request.origin() == null) {
|
||||
return null; // a put-mapping-request on old versions does not have origin.
|
||||
return Optional.empty(); // a put-mapping-request on old versions does not have origin.
|
||||
}
|
||||
final List<Index> followingIndices = Arrays.stream(indices)
|
||||
.filter(index -> {
|
||||
|
@ -98,8 +100,9 @@ public final class CcrRequests {
|
|||
final String errorMessage = "can't put mapping to the following indices "
|
||||
+ "[" + followingIndices.stream().map(Index::getName).collect(Collectors.joining(", ")) + "]; "
|
||||
+ "the mapping of the following indices are self-replicated from its leader indices";
|
||||
return new ElasticsearchStatusException(errorMessage, RestStatus.FORBIDDEN);
|
||||
return Optional.of(new ElasticsearchStatusException(errorMessage, RestStatus.FORBIDDEN));
|
||||
}
|
||||
return null;
|
||||
return Optional.empty();
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,8 @@ package org.elasticsearch.xpack.core;
|
|||
|
||||
import org.elasticsearch.action.ActionRequest;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.MappingRequestValidator;
|
||||
import org.elasticsearch.action.RequestValidators;
|
||||
import org.elasticsearch.action.admin.indices.mapping.put.PutMappingRequest;
|
||||
import org.elasticsearch.action.support.ActionFilter;
|
||||
import org.elasticsearch.bootstrap.BootstrapCheck;
|
||||
import org.elasticsearch.client.Client;
|
||||
|
@ -431,8 +432,10 @@ public class LocalStateCompositeXPackPlugin extends XPackPlugin implements Scrip
|
|||
}
|
||||
|
||||
@Override
|
||||
public Collection<MappingRequestValidator> mappingRequestValidators() {
|
||||
return filterPlugins(ActionPlugin.class).stream().flatMap(p -> p.mappingRequestValidators().stream())
|
||||
public Collection<RequestValidators.RequestValidator<PutMappingRequest>> mappingRequestValidators() {
|
||||
return filterPlugins(ActionPlugin.class)
|
||||
.stream()
|
||||
.flatMap(p -> p.mappingRequestValidators().stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue