[CCR] Add get auto follow pattern api (#33849)

Relates to #33007
This commit is contained in:
Martijn van Groningen 2018-09-24 20:26:13 +02:00 committed by GitHub
parent 1c579646d3
commit 2795ef561f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 451 additions and 11 deletions

View File

@ -5,9 +5,26 @@
leader_cluster_alias: _local_
body:
leader_index_patterns: ['logs-*']
max_concurrent_read_batches: 2
- is_true: acknowledged
- do:
ccr.get_auto_follow_pattern:
leader_cluster_alias: _local_
- match: { _local_.leader_index_patterns: ['logs-*'] }
- match: { _local_.max_concurrent_read_batches: 2 }
- do:
ccr.get_auto_follow_pattern: {}
- match: { _local_.leader_index_patterns: ['logs-*'] }
- match: { _local_.max_concurrent_read_batches: 2 }
- do:
ccr.delete_auto_follow_pattern:
leader_cluster_alias: _local_
- is_true: acknowledged
- do:
catch: missing
ccr.get_auto_follow_pattern:
leader_cluster_alias: _local_

View File

@ -40,10 +40,13 @@ import org.elasticsearch.threadpool.FixedExecutorBuilder;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.watcher.ResourceWatcherService;
import org.elasticsearch.xpack.ccr.action.AutoFollowCoordinator;
import org.elasticsearch.xpack.ccr.action.TransportGetAutoFollowPatternAction;
import org.elasticsearch.xpack.ccr.rest.RestGetAutoFollowPatternAction;
import org.elasticsearch.xpack.ccr.action.TransportAutoFollowStatsAction;
import org.elasticsearch.xpack.ccr.rest.RestAutoFollowStatsAction;
import org.elasticsearch.xpack.core.ccr.action.AutoFollowStatsAction;
import org.elasticsearch.xpack.core.ccr.action.DeleteAutoFollowPatternAction;
import org.elasticsearch.xpack.core.ccr.action.GetAutoFollowPatternAction;
import org.elasticsearch.xpack.core.ccr.action.PutAutoFollowPatternAction;
import org.elasticsearch.xpack.ccr.action.ShardChangesAction;
import org.elasticsearch.xpack.ccr.action.ShardFollowTask;
@ -163,7 +166,8 @@ public class Ccr extends Plugin implements ActionPlugin, PersistentTaskPlugin, E
new ActionHandler<>(UnfollowIndexAction.INSTANCE, TransportUnfollowIndexAction.class),
// auto-follow actions
new ActionHandler<>(DeleteAutoFollowPatternAction.INSTANCE, TransportDeleteAutoFollowPatternAction.class),
new ActionHandler<>(PutAutoFollowPatternAction.INSTANCE, TransportPutAutoFollowPatternAction.class));
new ActionHandler<>(PutAutoFollowPatternAction.INSTANCE, TransportPutAutoFollowPatternAction.class),
new ActionHandler<>(GetAutoFollowPatternAction.INSTANCE, TransportGetAutoFollowPatternAction.class));
}
public List<RestHandler> getRestHandlers(Settings settings, RestController restController, ClusterSettings clusterSettings,
@ -184,7 +188,8 @@ public class Ccr extends Plugin implements ActionPlugin, PersistentTaskPlugin, E
new RestUnfollowIndexAction(settings, restController),
// auto-follow APIs
new RestDeleteAutoFollowPatternAction(settings, restController),
new RestPutAutoFollowPatternAction(settings, restController));
new RestPutAutoFollowPatternAction(settings, restController),
new RestGetAutoFollowPatternAction(settings, restController));
}
public List<NamedWriteableRegistry.Entry> getNamedWriteables() {

View File

@ -0,0 +1,83 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.ccr.action;
import org.elasticsearch.ResourceNotFoundException;
import org.elasticsearch.action.ActionListener;
import org.elasticsearch.action.support.ActionFilters;
import org.elasticsearch.action.support.master.TransportMasterNodeReadAction;
import org.elasticsearch.cluster.ClusterState;
import org.elasticsearch.cluster.block.ClusterBlockException;
import org.elasticsearch.cluster.block.ClusterBlockLevel;
import org.elasticsearch.cluster.metadata.IndexNameExpressionResolver;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.cluster.service.ClusterService;
import org.elasticsearch.common.inject.Inject;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.threadpool.ThreadPool;
import org.elasticsearch.transport.TransportService;
import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata;
import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata.AutoFollowPattern;
import org.elasticsearch.xpack.core.ccr.action.GetAutoFollowPatternAction;
import java.util.Collections;
import java.util.Map;
public class TransportGetAutoFollowPatternAction
extends TransportMasterNodeReadAction<GetAutoFollowPatternAction.Request, GetAutoFollowPatternAction.Response> {
@Inject
public TransportGetAutoFollowPatternAction(Settings settings,
TransportService transportService,
ClusterService clusterService,
ThreadPool threadPool,
ActionFilters actionFilters,
IndexNameExpressionResolver indexNameExpressionResolver) {
super(settings, GetAutoFollowPatternAction.NAME, transportService, clusterService, threadPool, actionFilters,
GetAutoFollowPatternAction.Request::new, indexNameExpressionResolver);
}
@Override
protected String executor() {
return ThreadPool.Names.SAME;
}
@Override
protected GetAutoFollowPatternAction.Response newResponse() {
return new GetAutoFollowPatternAction.Response();
}
@Override
protected void masterOperation(GetAutoFollowPatternAction.Request request,
ClusterState state,
ActionListener<GetAutoFollowPatternAction.Response> listener) throws Exception {
Map<String, AutoFollowPattern> autoFollowPatterns = getAutoFollowPattern(state.metaData(), request.getLeaderClusterAlias());
listener.onResponse(new GetAutoFollowPatternAction.Response(autoFollowPatterns));
}
@Override
protected ClusterBlockException checkBlock(GetAutoFollowPatternAction.Request request, ClusterState state) {
return state.blocks().globalBlockedException(ClusterBlockLevel.METADATA_READ);
}
static Map<String, AutoFollowPattern> getAutoFollowPattern(MetaData metaData, String leaderClusterAlias) {
AutoFollowMetadata autoFollowMetadata = metaData.custom(AutoFollowMetadata.TYPE);
if (autoFollowMetadata == null) {
throw new ResourceNotFoundException("no auto-follow patterns for cluster alias [{}] found", leaderClusterAlias);
}
if (leaderClusterAlias == null) {
return autoFollowMetadata.getPatterns();
}
AutoFollowPattern autoFollowPattern = autoFollowMetadata.getPatterns().get(leaderClusterAlias);
if (autoFollowPattern == null) {
throw new ResourceNotFoundException("no auto-follow patterns for cluster alias [{}] found", leaderClusterAlias);
}
return Collections.singletonMap(leaderClusterAlias, autoFollowPattern);
}
}

View File

@ -0,0 +1,40 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.ccr.rest;
import org.elasticsearch.client.node.NodeClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.rest.BaseRestHandler;
import org.elasticsearch.rest.RestController;
import org.elasticsearch.rest.RestRequest;
import org.elasticsearch.rest.action.RestToXContentListener;
import org.elasticsearch.xpack.core.ccr.action.GetAutoFollowPatternAction.Request;
import java.io.IOException;
import static org.elasticsearch.xpack.core.ccr.action.GetAutoFollowPatternAction.INSTANCE;
public class RestGetAutoFollowPatternAction extends BaseRestHandler {
public RestGetAutoFollowPatternAction(Settings settings, RestController controller) {
super(settings);
controller.registerHandler(RestRequest.Method.GET, "/_ccr/auto_follow/{leader_cluster_alias}", this);
controller.registerHandler(RestRequest.Method.GET, "/_ccr/auto_follow", this);
}
@Override
public String getName() {
return "ccr_get_auto_follow_pattern_action";
}
@Override
protected RestChannelConsumer prepareRequest(RestRequest restRequest, NodeClient client) throws IOException {
Request request = new Request();
request.setLeaderClusterAlias(restRequest.param("leader_cluster_alias"));
return channel -> client.execute(INSTANCE, request, new RestToXContentListener<>(channel));
}
}

View File

@ -0,0 +1,27 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.ccr.action;
import org.elasticsearch.common.io.stream.Writeable;
import org.elasticsearch.test.AbstractWireSerializingTestCase;
import org.elasticsearch.xpack.core.ccr.action.GetAutoFollowPatternAction;
public class GetAutoFollowPatternRequestTests extends AbstractWireSerializingTestCase<GetAutoFollowPatternAction.Request> {
@Override
protected Writeable.Reader<GetAutoFollowPatternAction.Request> instanceReader() {
return GetAutoFollowPatternAction.Request::new;
}
@Override
protected GetAutoFollowPatternAction.Request createTestInstance() {
GetAutoFollowPatternAction.Request request = new GetAutoFollowPatternAction.Request();
if (randomBoolean()) {
request.setLeaderClusterAlias(randomAlphaOfLength(4));
}
return request;
}
}

View File

@ -0,0 +1,43 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.ccr.action;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.test.AbstractStreamableTestCase;
import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata.AutoFollowPattern;
import org.elasticsearch.xpack.core.ccr.action.GetAutoFollowPatternAction;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class GetAutoFollowPatternResponseTests extends AbstractStreamableTestCase<GetAutoFollowPatternAction.Response> {
@Override
protected GetAutoFollowPatternAction.Response createBlankInstance() {
return new GetAutoFollowPatternAction.Response();
}
@Override
protected GetAutoFollowPatternAction.Response createTestInstance() {
int numPatterns = randomIntBetween(1, 8);
Map<String, AutoFollowPattern> patterns = new HashMap<>(numPatterns);
for (int i = 0; i < numPatterns; i++) {
AutoFollowPattern autoFollowPattern = new AutoFollowPattern(
Collections.singletonList(randomAlphaOfLength(4)),
randomAlphaOfLength(4),
randomIntBetween(0, Integer.MAX_VALUE),
randomIntBetween(0, Integer.MAX_VALUE),
randomNonNegativeLong(),
randomIntBetween(0, Integer.MAX_VALUE),
randomIntBetween(0, Integer.MAX_VALUE),
TimeValue.timeValueMillis(500),
TimeValue.timeValueMillis(500));
patterns.put(randomAlphaOfLength(4), autoFollowPattern);
}
return new GetAutoFollowPatternAction.Response(patterns);
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.ccr.action;
import org.elasticsearch.ResourceNotFoundException;
import org.elasticsearch.cluster.metadata.MetaData;
import org.elasticsearch.test.ESTestCase;
import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata;
import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata.AutoFollowPattern;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.hamcrest.Matchers.equalTo;
import static org.hamcrest.collection.IsMapContaining.hasEntry;
public class TransportGetAutoFollowPatternActionTests extends ESTestCase {
public void testGetAutoFollowPattern() {
Map<String, AutoFollowPattern> patterns = new HashMap<>();
patterns.put("test_alias1",
new AutoFollowPattern(Collections.singletonList("index-*"), null, null, null, null, null, null, null, null));
patterns.put("test_alias2",
new AutoFollowPattern(Collections.singletonList("index-*"), null, null, null, null, null, null, null, null));
MetaData metaData = MetaData.builder()
.putCustom(AutoFollowMetadata.TYPE, new AutoFollowMetadata(patterns, Collections.emptyMap(), Collections.emptyMap()))
.build();
Map<String, AutoFollowPattern> result = TransportGetAutoFollowPatternAction.getAutoFollowPattern(metaData, "test_alias1");
assertThat(result.size(), equalTo(1));
assertThat(result, hasEntry("test_alias1", patterns.get("test_alias1")));
result = TransportGetAutoFollowPatternAction.getAutoFollowPattern(metaData, null);
assertThat(result.size(), equalTo(2));
assertThat(result, hasEntry("test_alias1", patterns.get("test_alias1")));
assertThat(result, hasEntry("test_alias2", patterns.get("test_alias2")));
expectThrows(ResourceNotFoundException.class,
() -> TransportGetAutoFollowPatternAction.getAutoFollowPattern(metaData, "another_alias"));
}
public void testGetAutoFollowPatternNoAutoFollowPatterns() {
AutoFollowMetadata autoFollowMetadata =
new AutoFollowMetadata(Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap());
MetaData metaData = MetaData.builder()
.putCustom(AutoFollowMetadata.TYPE, autoFollowMetadata)
.build();
expectThrows(ResourceNotFoundException.class,
() -> TransportGetAutoFollowPatternAction.getAutoFollowPattern(metaData, "test_alias"));
}
public void testGetAutoFollowPatternNoAutoFollowMetadata() {
MetaData metaData = MetaData.builder().build();
expectThrows(ResourceNotFoundException.class,
() -> TransportGetAutoFollowPatternAction.getAutoFollowPattern(metaData, "test_alias"));
}
}

View File

@ -170,8 +170,8 @@ public class AutoFollowMetadata extends AbstractNamedDiffable<MetaData.Custom> i
public static class AutoFollowPattern implements Writeable, ToXContentObject {
private static final ParseField LEADER_PATTERNS_FIELD = new ParseField("leader_patterns");
private static final ParseField FOLLOW_PATTERN_FIELD = new ParseField("follow_pattern");
public static final ParseField LEADER_PATTERNS_FIELD = new ParseField("leader_index_patterns");
public static final ParseField FOLLOW_PATTERN_FIELD = new ParseField("follow_index_pattern");
public static final ParseField MAX_BATCH_OPERATION_COUNT = new ParseField("max_batch_operation_count");
public static final ParseField MAX_CONCURRENT_READ_BATCHES = new ParseField("max_concurrent_read_batches");
public static final ParseField MAX_BATCH_SIZE_IN_BYTES = new ParseField("max_batch_size_in_bytes");

View File

@ -0,0 +1,135 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.xpack.core.ccr.action;
import org.elasticsearch.action.Action;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.action.ActionResponse;
import org.elasticsearch.action.support.master.MasterNodeReadRequest;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;
import org.elasticsearch.common.xcontent.ToXContentObject;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.xpack.core.ccr.AutoFollowMetadata.AutoFollowPattern;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
public class GetAutoFollowPatternAction extends Action<GetAutoFollowPatternAction.Response> {
public static final String NAME = "cluster:admin/xpack/ccr/auto_follow_pattern/get";
public static final GetAutoFollowPatternAction INSTANCE = new GetAutoFollowPatternAction();
private GetAutoFollowPatternAction() {
super(NAME);
}
@Override
public Response newResponse() {
return new Response();
}
public static class Request extends MasterNodeReadRequest<Request> {
private String leaderClusterAlias;
public Request() {
}
public Request(StreamInput in) throws IOException {
super(in);
this.leaderClusterAlias = in.readOptionalString();
}
@Override
public ActionRequestValidationException validate() {
return null;
}
public String getLeaderClusterAlias() {
return leaderClusterAlias;
}
public void setLeaderClusterAlias(String leaderClusterAlias) {
this.leaderClusterAlias = leaderClusterAlias;
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeOptionalString(leaderClusterAlias);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Request request = (Request) o;
return Objects.equals(leaderClusterAlias, request.leaderClusterAlias);
}
@Override
public int hashCode() {
return Objects.hash(leaderClusterAlias);
}
}
public static class Response extends ActionResponse implements ToXContentObject {
private Map<String, AutoFollowPattern> autoFollowPatterns;
public Response(Map<String, AutoFollowPattern> autoFollowPatterns) {
this.autoFollowPatterns = autoFollowPatterns;
}
public Response() {
}
public Map<String, AutoFollowPattern> getAutoFollowPatterns() {
return autoFollowPatterns;
}
@Override
public void readFrom(StreamInput in) throws IOException {
super.readFrom(in);
autoFollowPatterns = in.readMap(StreamInput::readString, AutoFollowPattern::new);
}
@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
out.writeMap(autoFollowPatterns, StreamOutput::writeString, (out1, value) -> value.writeTo(out1));
}
@Override
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject();
for (Map.Entry<String, AutoFollowPattern> entry : autoFollowPatterns.entrySet()) {
builder.startObject(entry.getKey());
entry.getValue().toXContent(builder, params);
builder.endObject();
}
builder.endObject();
return builder;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Response response = (Response) o;
return Objects.equals(autoFollowPatterns, response.autoFollowPatterns);
}
@Override
public int hashCode() {
return Objects.hash(autoFollowPatterns);
}
}
}

View File

@ -42,15 +42,13 @@ public class PutAutoFollowPatternAction extends Action<AcknowledgedResponse> {
public static class Request extends AcknowledgedRequest<Request> implements ToXContentObject {
static final ParseField LEADER_CLUSTER_ALIAS_FIELD = new ParseField("leader_cluster_alias");
static final ParseField LEADER_INDEX_PATTERNS_FIELD = new ParseField("leader_index_patterns");
static final ParseField FOLLOW_INDEX_NAME_PATTERN_FIELD = new ParseField("follow_index_name_pattern");
private static final ObjectParser<Request, String> PARSER = new ObjectParser<>("put_auto_follow_pattern_request", Request::new);
static {
PARSER.declareString(Request::setLeaderClusterAlias, LEADER_CLUSTER_ALIAS_FIELD);
PARSER.declareStringArray(Request::setLeaderIndexPatterns, LEADER_INDEX_PATTERNS_FIELD);
PARSER.declareString(Request::setFollowIndexNamePattern, FOLLOW_INDEX_NAME_PATTERN_FIELD);
PARSER.declareStringArray(Request::setLeaderIndexPatterns, AutoFollowPattern.LEADER_PATTERNS_FIELD);
PARSER.declareString(Request::setFollowIndexNamePattern, AutoFollowPattern.FOLLOW_PATTERN_FIELD);
PARSER.declareInt(Request::setMaxBatchOperationCount, AutoFollowPattern.MAX_BATCH_OPERATION_COUNT);
PARSER.declareInt(Request::setMaxConcurrentReadBatches, AutoFollowPattern.MAX_CONCURRENT_READ_BATCHES);
PARSER.declareLong(Request::setMaxOperationSizeInBytes, AutoFollowPattern.MAX_BATCH_SIZE_IN_BYTES);
@ -98,7 +96,7 @@ public class PutAutoFollowPatternAction extends Action<AcknowledgedResponse> {
"] is missing", validationException);
}
if (leaderIndexPatterns == null || leaderIndexPatterns.isEmpty()) {
validationException = addValidationError("[" + LEADER_INDEX_PATTERNS_FIELD.getPreferredName() +
validationException = addValidationError("[" + AutoFollowPattern.LEADER_PATTERNS_FIELD.getPreferredName() +
"] is missing", validationException);
}
if (maxRetryDelay != null) {
@ -232,9 +230,9 @@ public class PutAutoFollowPatternAction extends Action<AcknowledgedResponse> {
builder.startObject();
{
builder.field(LEADER_CLUSTER_ALIAS_FIELD.getPreferredName(), leaderClusterAlias);
builder.field(LEADER_INDEX_PATTERNS_FIELD.getPreferredName(), leaderIndexPatterns);
builder.field(AutoFollowPattern.LEADER_PATTERNS_FIELD.getPreferredName(), leaderIndexPatterns);
if (followIndexNamePattern != null) {
builder.field(FOLLOW_INDEX_NAME_PATTERN_FIELD.getPreferredName(), followIndexNamePattern);
builder.field(AutoFollowPattern.FOLLOW_PATTERN_FIELD.getPreferredName(), followIndexNamePattern);
}
if (maxBatchOperationCount != null) {
builder.field(AutoFollowPattern.MAX_BATCH_OPERATION_COUNT.getPreferredName(), maxBatchOperationCount);

View File

@ -15,6 +15,7 @@ import org.elasticsearch.xpack.core.ccr.action.CcrStatsAction;
import org.elasticsearch.xpack.core.ccr.action.CreateAndFollowIndexAction;
import org.elasticsearch.xpack.core.ccr.action.DeleteAutoFollowPatternAction;
import org.elasticsearch.xpack.core.ccr.action.FollowIndexAction;
import org.elasticsearch.xpack.core.ccr.action.GetAutoFollowPatternAction;
import org.elasticsearch.xpack.core.ccr.action.PutAutoFollowPatternAction;
import org.elasticsearch.xpack.core.ccr.action.UnfollowIndexAction;
@ -96,4 +97,16 @@ public class CcrClient {
return listener;
}
public void getAutoFollowPattern(
final GetAutoFollowPatternAction.Request request,
final ActionListener<GetAutoFollowPatternAction.Response> listener) {
client.execute(GetAutoFollowPatternAction.INSTANCE, request, listener);
}
public ActionFuture<GetAutoFollowPatternAction.Response> getAutoFollowPattern(final GetAutoFollowPatternAction.Request request) {
final PlainActionFuture<GetAutoFollowPatternAction.Response> listener = PlainActionFuture.newFuture();
client.execute(GetAutoFollowPatternAction.INSTANCE, request, listener);
return listener;
}
}

View File

@ -0,0 +1,16 @@
{
"ccr.get_auto_follow_pattern": {
"documentation": "http://www.elastic.co/guide/en/elasticsearch/reference/current",
"methods": [ "GET" ],
"url": {
"path": "/_ccr/auto_follow/{leader_cluster_alias}",
"paths": [ "/_ccr/auto_follow", "/_ccr/auto_follow/{leader_cluster_alias}" ],
"parts": {
"leader_cluster_alias": {
"type": "string",
"description": "The name of the leader cluster alias."
}
}
}
}
}