step by step
This commit is contained in:
parent
fe22c08207
commit
d63cd8c9c3
|
@ -6,13 +6,11 @@
|
|||
package org.elasticsearch.xpack.core.indexlifecycle;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
|
||||
import org.elasticsearch.action.support.ActiveShardCount;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.routing.ShardRouting;
|
||||
import org.elasticsearch.cluster.routing.allocation.RoutingAllocation;
|
||||
import org.elasticsearch.cluster.routing.allocation.decider.AllocationDeciders;
|
||||
|
@ -30,14 +28,15 @@ import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.IndexNotFoundException;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
public class AllocateAction implements LifecycleAction {
|
||||
|
||||
|
@ -145,35 +144,22 @@ public class AllocateAction implements LifecycleAction {
|
|||
}).forEach(e -> newSettingsBuilder.put(settingPrefix + e.getKey(), e.getValue()));
|
||||
}
|
||||
|
||||
void execute(Index index, BiConsumer<Settings, Listener> settingsUpdater, ClusterState clusterState, ClusterSettings clusterSettings,
|
||||
Listener listener) {
|
||||
// We only want to make progress if all shards are active so check that
|
||||
// first
|
||||
if (ActiveShardCount.ALL.enoughShardsActive(clusterState, index.getName()) == false) {
|
||||
public static ConditionalWaitStep getAllocationCheck(AllocationDeciders allocationDeciders, String phase, String index) {
|
||||
return new ConditionalWaitStep("wait_allocation", NAME,
|
||||
phase, index, (clusterState) -> {
|
||||
// We only want to make progress if all shards are active so check that first
|
||||
if (ActiveShardCount.ALL.enoughShardsActive(clusterState, index) == false) {
|
||||
logger.debug("[{}] lifecycle action for index [{}] cannot make progress because not all shards are active", NAME,
|
||||
index.getName());
|
||||
listener.onSuccess(false);
|
||||
return;
|
||||
index);
|
||||
return false;
|
||||
}
|
||||
IndexMetaData idxMeta = clusterState.metaData().index(index);
|
||||
if (idxMeta == null) {
|
||||
listener.onFailure(
|
||||
new IndexNotFoundException("Index not found when executing " + NAME + " lifecycle action.", index.getName()));
|
||||
return;
|
||||
}
|
||||
Settings existingSettings = idxMeta.getSettings();
|
||||
Settings.Builder newSettings = Settings.builder();
|
||||
addMissingAttrs(include, IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey(), existingSettings, newSettings);
|
||||
addMissingAttrs(exclude, IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey(), existingSettings, newSettings);
|
||||
addMissingAttrs(require, IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey(), existingSettings, newSettings);
|
||||
Settings newAllocationIncludes = newSettings.build();
|
||||
if (newAllocationIncludes.isEmpty()) {
|
||||
|
||||
// All the allocation attributes are already set so just need to
|
||||
// check if the allocation has happened
|
||||
RoutingAllocation allocation = new RoutingAllocation(allocationDeciders, clusterState.getRoutingNodes(), clusterState, null,
|
||||
System.nanoTime());
|
||||
int allocationPendingShards = 0;
|
||||
List<ShardRouting> allShards = clusterState.getRoutingTable().allShards(index.getName());
|
||||
List<ShardRouting> allShards = clusterState.getRoutingTable().allShards(index);
|
||||
for (ShardRouting shardRouting : allShards) {
|
||||
assert shardRouting.active() : "Shard not active, found " + shardRouting.state() + "for shard with id: "
|
||||
+ shardRouting.shardId();
|
||||
|
@ -186,37 +172,34 @@ public class AllocateAction implements LifecycleAction {
|
|||
}
|
||||
if (allocationPendingShards > 0) {
|
||||
logger.debug("[{}] lifecycle action for index [{}] waiting for [{}] shards "
|
||||
+ "to be allocated to nodes matching the given filters", NAME, index.getName(), allocationPendingShards);
|
||||
listener.onSuccess(false);
|
||||
+ "to be allocated to nodes matching the given filters", NAME, index, allocationPendingShards);
|
||||
return false;
|
||||
} else {
|
||||
logger.debug("[{}] lifecycle action for index [{}] complete", NAME, index.getName());
|
||||
listener.onSuccess(true);
|
||||
}
|
||||
} else {
|
||||
// We have some allocation attributes to set
|
||||
settingsUpdater.accept(newAllocationIncludes, listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Index index, Client client, ClusterService clusterService, Listener listener) {
|
||||
ClusterState clusterState = clusterService.state();
|
||||
BiConsumer<Settings, Listener> settingsUpdater = (s, l) -> {
|
||||
|
||||
client.admin().indices().updateSettings(new UpdateSettingsRequest(s, index.getName()),
|
||||
new ActionListener<UpdateSettingsResponse>() {
|
||||
@Override
|
||||
public void onResponse(UpdateSettingsResponse updateSettingsResponse) {
|
||||
l.onSuccess(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
l.onFailure(e);
|
||||
logger.debug("[{}] lifecycle action for index [{}] complete", NAME, index);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
};
|
||||
execute(index, settingsUpdater, clusterState, clusterService.getClusterSettings(), listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Step> toSteps(String phase, Index index, Client client, ThreadPool threadPool, LongSupplier nowSupplier) {
|
||||
ClusterStateUpdateStep updateAllocationSettings = new ClusterStateUpdateStep(
|
||||
"update_allocation", NAME, phase, index.getName(), (clusterState) -> {
|
||||
IndexMetaData idxMeta = clusterState.metaData().index(index);
|
||||
if (idxMeta == null) {
|
||||
return clusterState;
|
||||
}
|
||||
Settings existingSettings = idxMeta.getSettings();
|
||||
Settings.Builder newSettings = Settings.builder();
|
||||
addMissingAttrs(include, IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey(), existingSettings, newSettings);
|
||||
addMissingAttrs(exclude, IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey(), existingSettings, newSettings);
|
||||
addMissingAttrs(require, IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey(), existingSettings, newSettings);
|
||||
return ClusterState.builder(clusterState)
|
||||
.metaData(MetaData.builder(clusterState.metaData())
|
||||
.updateSettings(newSettings.build(), index.getName())).build();
|
||||
});
|
||||
|
||||
return Arrays.asList(updateAllocationSettings, getAllocationCheck(allocationDeciders, phase, index.getName()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.ActionRequestBuilder;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Step;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.StepResult;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ClientStep<RequestBuilder extends ActionRequestBuilder, Response extends ActionResponse> extends Step {
|
||||
|
||||
private final RequestBuilder requestBuilder;
|
||||
private final Function<ClusterState, Boolean> checkComplete;
|
||||
private final Function<Response, Boolean> checkSuccess;
|
||||
private Exception returnedException;
|
||||
private boolean returnedSuccess;
|
||||
|
||||
public ClientStep(String name, String action, String phase, String index, RequestBuilder requestBuilder,
|
||||
Function<ClusterState, Boolean> checkComplete, Function<Response, Boolean> checkSuccess) {
|
||||
super(name, action, phase, index);
|
||||
this.requestBuilder = requestBuilder;
|
||||
this.checkComplete = checkComplete;
|
||||
this.checkSuccess = checkSuccess;
|
||||
this.returnedException = null;
|
||||
this.returnedSuccess = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StepResult execute(ClusterState currentState) {
|
||||
if (checkComplete.apply(currentState)) {
|
||||
return new StepResult("client-complete", null, currentState, true, true);
|
||||
} else {
|
||||
requestBuilder.execute(new ActionListener<Response>() {
|
||||
@Override
|
||||
public void onResponse(Response r) {
|
||||
if (checkSuccess.apply(r)) {
|
||||
returnedSuccess = true;
|
||||
}
|
||||
// IndexLifecycleService.triggerPolicies()
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
returnedException = e;
|
||||
}
|
||||
});
|
||||
return new StepResult("client-in-progress", null, currentState, true, false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Step;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.StepResult;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ClusterStateUpdateStep extends Step {
|
||||
private final String name;
|
||||
private final String index;
|
||||
private final String phase;
|
||||
private final String action;
|
||||
private final Function<ClusterState, ClusterState> updateTask;
|
||||
|
||||
public ClusterStateUpdateStep(String name, String index, String phase, String action, Function<ClusterState, ClusterState> updateTask) {
|
||||
super(name, action, phase, index);
|
||||
this.name = name;
|
||||
this.index = index;
|
||||
this.phase = phase;
|
||||
this.action = action;
|
||||
this.updateTask = updateTask;
|
||||
}
|
||||
|
||||
public StepResult execute(ClusterState clusterState) {
|
||||
ClusterState updated = null;
|
||||
try {
|
||||
updated = updateTask.apply(clusterState);
|
||||
return new StepResult("done!", null, updated, true, true);
|
||||
} catch (Exception e) {
|
||||
return new StepResult("something went wrong", e, updated, true, true);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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.core.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Step;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.StepResult;
|
||||
|
||||
import java.util.function.Function;
|
||||
|
||||
public class ConditionalWaitStep extends Step {
|
||||
private final Function<ClusterState, Boolean> condition;
|
||||
|
||||
public ConditionalWaitStep(String name, String index, String phase, String action, Function<ClusterState, Boolean> condition) {
|
||||
super(name, action, phase, index);
|
||||
this.condition = condition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public StepResult execute(ClusterState currentState) {
|
||||
boolean isComplete = condition.apply(currentState);
|
||||
return new StepResult(String.valueOf(isComplete), null, currentState, true, isComplete);
|
||||
}
|
||||
}
|
|
@ -6,8 +6,8 @@
|
|||
package org.elasticsearch.xpack.core.indexlifecycle;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequestBuilder;
|
||||
import org.elasticsearch.action.admin.indices.delete.DeleteIndexResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
|
@ -19,8 +19,12 @@ import org.elasticsearch.common.xcontent.ObjectParser;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
/**
|
||||
* A {@link LifecycleAction} which deletes the index.
|
||||
|
@ -63,18 +67,11 @@ public class DeleteAction implements LifecycleAction {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void execute(Index index, Client client, ClusterService clusterService, Listener listener) {
|
||||
client.admin().indices().delete(new DeleteIndexRequest(index.getName()), new ActionListener<DeleteIndexResponse>() {
|
||||
@Override
|
||||
public void onResponse(DeleteIndexResponse deleteIndexResponse) {
|
||||
listener.onSuccess(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
listener.onFailure(e);
|
||||
}
|
||||
});
|
||||
public List<Step> toSteps(String phase, Index index, Client client, ThreadPool threadPool, LongSupplier nowSupplier) {
|
||||
String indexName = index.getName();
|
||||
return Collections.singletonList(new ClientStep<DeleteIndexRequestBuilder, DeleteIndexResponse>( "delete",
|
||||
NAME, phase, indexName, client.admin().indices().prepareDelete(indexName),
|
||||
clusterState -> clusterState.metaData().hasIndex(indexName), response -> true));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -8,10 +8,16 @@ package org.elasticsearch.xpack.core.indexlifecycle;
|
|||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.ActionResponse;
|
||||
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequest;
|
||||
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeRequestBuilder;
|
||||
import org.elasticsearch.action.admin.indices.forcemerge.ForceMergeResponse;
|
||||
import org.elasticsearch.action.admin.indices.segments.IndicesSegmentResponse;
|
||||
import org.elasticsearch.action.admin.indices.segments.IndicesSegmentsRequest;
|
||||
import org.elasticsearch.action.admin.indices.segments.IndicesSegmentsRequestBuilder;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.Strings;
|
||||
|
@ -23,11 +29,14 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
|
@ -87,107 +96,37 @@ public class ForceMergeAction implements LifecycleAction {
|
|||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to check if a force-merge is necessary based on {@code maxNumSegments} and then calls
|
||||
* the next {@code action}.
|
||||
*
|
||||
* @param index The specific index to check the segments of
|
||||
* @param client The client to execute the transport actions
|
||||
* @param listener The listener to call onFailure on if an exception occurs when executing the {@link IndicesSegmentsRequest}
|
||||
* @param nextAction The next action to execute if there are too many segments and force-merge is appropriate
|
||||
* @param skipToAction The next action to execute if there aren't too many segments
|
||||
*/
|
||||
void checkSegments(Index index, Client client, Listener listener, Consumer<ActionResponse> nextAction,
|
||||
Consumer<ActionResponse> skipToAction) {
|
||||
client.admin().indices().segments(new IndicesSegmentsRequest(index.getName()), ActionListener.wrap(r -> {
|
||||
boolean hasTooManySegments = StreamSupport.stream(r.getIndices().get(index.getName()).spliterator(), false)
|
||||
.anyMatch(iss -> Arrays.stream(iss.getShards()).anyMatch(p -> p.getSegments().size() > maxNumSegments));
|
||||
if (nextAction != null && hasTooManySegments && RestStatus.OK.equals(r.getStatus())) {
|
||||
nextAction.accept(r);
|
||||
} else {
|
||||
skipToAction.accept(r);
|
||||
}
|
||||
}, listener::onFailure));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to execute the force-merge
|
||||
*
|
||||
* @param index The specific index to force-merge
|
||||
* @param client The client to execute the transport actions
|
||||
* @param listener The listener to call onFailure on if an exception occurs when executing the {@link ForceMergeRequest}
|
||||
* @param nextAction The next action to execute if the force-merge is successful
|
||||
*/
|
||||
void forceMerge(Index index, Client client, Listener listener, Consumer<ActionResponse> nextAction) {
|
||||
ForceMergeRequest forceMergeRequest = new ForceMergeRequest(index.getName()).maxNumSegments(maxNumSegments);
|
||||
client.admin().indices().forceMerge(forceMergeRequest, ActionListener.wrap(r -> {
|
||||
if (RestStatus.OK.equals(r.getStatus())) {
|
||||
nextAction.accept(r);
|
||||
}
|
||||
}, listener::onFailure));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to prepare the index for force-merging by making it read-only
|
||||
*
|
||||
* @param index The specific index to set as read-only
|
||||
* @param client The client to execute the transport actions
|
||||
* @param listener The listener to call onFailure on if an exception occurs when executing the {@link UpdateSettingsRequest}
|
||||
* @param nextAction The next action to execute if updating the setting is successful
|
||||
*/
|
||||
void updateBlockWriteSettingToReadOnly(Index index, Client client, Listener listener, Consumer<ActionResponse> nextAction) {
|
||||
UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(Settings.builder()
|
||||
.put(IndexMetaData.SETTING_BLOCKS_WRITE, true).build(), index.getName());
|
||||
client.admin().indices().updateSettings(updateSettingsRequest, ActionListener.wrap(response -> {
|
||||
nextAction.accept(response);
|
||||
}, listener::onFailure));
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to return the index back to read-write mode since force-merging was successful
|
||||
*
|
||||
* @param index The specific index to set back as read-write
|
||||
* @param client The client to execute the transport actions
|
||||
* @param listener The listener to return a final response to for this {@link ForceMergeAction}.
|
||||
*/
|
||||
void updateBlockWriteSettingToReadWrite(Index index, Client client, Listener listener) {
|
||||
UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(Settings.builder()
|
||||
.put(IndexMetaData.SETTING_BLOCKS_WRITE, false).build(), index.getName());
|
||||
client.admin().indices().updateSettings(updateSettingsRequest, ActionListener.wrap(
|
||||
response -> listener.onSuccess(true), listener::onFailure));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Index index, Client client, ClusterService clusterService, Listener listener) {
|
||||
boolean isReadOnly = clusterService.state().metaData().indices().get(index.getName()).getSettings()
|
||||
.getAsBoolean(IndexMetaData.SETTING_BLOCKS_WRITE, false);
|
||||
if (isReadOnly) {
|
||||
// index is already read-only, so just check if a force-merge is necessary and set back
|
||||
// to read-write whether a force-merge is necessary or not.
|
||||
checkSegments(index, client, listener, r1 ->
|
||||
forceMerge(index, client, listener,
|
||||
// after a successful force-merge, return the index to read-write
|
||||
r2 -> updateBlockWriteSettingToReadWrite(index, client, listener)),
|
||||
r3 -> updateBlockWriteSettingToReadWrite(index, client, listener));
|
||||
} else {
|
||||
// first check if a force-merge is appropriate
|
||||
checkSegments(index, client, listener,
|
||||
// if appropriate, set the index to read-only
|
||||
r1 -> updateBlockWriteSettingToReadOnly(index, client, listener,
|
||||
// once the index is read-only, run a force-merge on it
|
||||
r2 -> forceMerge(index, client, listener,
|
||||
// after a successful force-merge, return the index to read-write
|
||||
r3 -> updateBlockWriteSettingToReadWrite(index, client, listener))),
|
||||
r4 -> {
|
||||
if (isReadOnly) {
|
||||
updateBlockWriteSettingToReadWrite(index, client, listener);
|
||||
} else {
|
||||
listener.onSuccess(true);
|
||||
}
|
||||
public List<Step> toSteps(String phase, Index index, Client client, ThreadPool threadPool, LongSupplier nowSupplier) {
|
||||
ClusterStateUpdateStep readOnlyStep = new ClusterStateUpdateStep(
|
||||
"read_only", NAME, phase, index.getName(), (currentState) -> {
|
||||
Settings readOnlySettings = Settings.builder().put(IndexMetaData.SETTING_BLOCKS_WRITE, true).build();
|
||||
return ClusterState.builder(currentState).metaData(MetaData.builder(currentState.metaData())
|
||||
.updateSettings(readOnlySettings, index.getName())).build();
|
||||
});
|
||||
}
|
||||
|
||||
ClientStep<IndicesSegmentsRequestBuilder, IndicesSegmentResponse> segmentCount = new ClientStep<>( "segment_count",
|
||||
NAME, phase, index.getName(),
|
||||
client.admin().indices().prepareSegments(index.getName()),
|
||||
currentState -> false, response -> {
|
||||
// check if has too many segments
|
||||
return StreamSupport.stream(response.getIndices().get(index.getName()).spliterator(), false)
|
||||
.anyMatch(iss -> Arrays.stream(iss.getShards()).anyMatch(p -> p.getSegments().size() > maxNumSegments));
|
||||
});
|
||||
|
||||
ClientStep forceMerge = new ClientStep<ForceMergeRequestBuilder, ForceMergeResponse>( "force_merge",
|
||||
NAME, phase, index.getName(),
|
||||
client.admin().indices().prepareForceMerge(index.getName()).setMaxNumSegments(maxNumSegments),
|
||||
currentState -> false, response -> RestStatus.OK.equals(response.getStatus()));
|
||||
|
||||
ClusterStateUpdateStep readWriteStep = new ClusterStateUpdateStep(
|
||||
"read_only", NAME, phase, index.getName(), (currentState) -> {
|
||||
Settings readOnlySettings = Settings.builder().put(IndexMetaData.SETTING_BLOCKS_WRITE, false).build();
|
||||
return ClusterState.builder(currentState).metaData(MetaData.builder(currentState.metaData())
|
||||
.updateSettings(readOnlySettings, index.getName())).build();
|
||||
});
|
||||
|
||||
return Arrays.asList(readOnlyStep, segmentCount, forceMerge, readWriteStep);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,108 +0,0 @@
|
|||
/*
|
||||
* 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.indexlifecycle;
|
||||
|
||||
/**
|
||||
* Provides the context to a {@link LifecyclePolicy} for a particular target.
|
||||
* This context provides the state of the lifecycle target (hereafter referred
|
||||
* to as the target) as well as allow operations to be performed on the target.
|
||||
*/
|
||||
public interface IndexLifecycleContext {
|
||||
|
||||
/**
|
||||
* Sets the phase for the target and calls the provided callback. Note that
|
||||
* this will also set the action name to an empty {@link String}.
|
||||
*
|
||||
* @param phase
|
||||
* the name of the phase to be set.
|
||||
* @param listener
|
||||
* a {@link Listener} to call after the operation.
|
||||
*/
|
||||
void setPhase(String phase, Listener listener);
|
||||
|
||||
/**
|
||||
* Sets the action for the target and calls the provided callback.
|
||||
*
|
||||
* @param action
|
||||
* the name of the action to be set.
|
||||
* @param listener
|
||||
* a {@link Listener} to call after the operation.
|
||||
*/
|
||||
void setAction(String action, Listener listener);
|
||||
|
||||
/**
|
||||
* @return the current {@link LifecycleAction} name for the target.
|
||||
*/
|
||||
String getAction();
|
||||
|
||||
/**
|
||||
* @return the start time of the current {@link LifecycleAction}.
|
||||
*/
|
||||
long getActionTime();
|
||||
|
||||
/**
|
||||
* @return the current {@link Phase} name for the target.
|
||||
*/
|
||||
String getPhase();
|
||||
|
||||
/**
|
||||
* @return the start time of the current {@link Phase}.
|
||||
*/
|
||||
long getPhaseTime();
|
||||
|
||||
/**
|
||||
* @return the name of the target.
|
||||
*/
|
||||
String getLifecycleTarget();
|
||||
|
||||
/**
|
||||
* @return the current index context's replica count.
|
||||
*/
|
||||
int getNumberOfReplicas();
|
||||
|
||||
/**
|
||||
* Determines whether the target is able to move to the provided
|
||||
* {@link Phase}
|
||||
*
|
||||
* @param phase
|
||||
* the {@link Phase} to test
|
||||
* @return <code>true</code> iff the target is ready to move to the
|
||||
* {@link Phase}.
|
||||
*/
|
||||
boolean canExecute(Phase phase);
|
||||
|
||||
/**
|
||||
* Executes the provided {@link LifecycleAction} passing the relevant target
|
||||
* state to it.
|
||||
*
|
||||
* @param action
|
||||
* the {@link LifecycleAction} to execute.
|
||||
* @param listener
|
||||
* a {@link LifecycleAction.Listener} to pass to the
|
||||
* {@link LifecycleAction}.
|
||||
*/
|
||||
void executeAction(LifecycleAction action, LifecycleAction.Listener listener);
|
||||
|
||||
/**
|
||||
* A callback for use when setting phase or action names.
|
||||
*/
|
||||
interface Listener {
|
||||
|
||||
/**
|
||||
* Called if the call to set the action/phase name was successful.
|
||||
*/
|
||||
void onSuccess();
|
||||
|
||||
/**
|
||||
* Called if there was an exception when setting the action or phase
|
||||
* name.
|
||||
*
|
||||
* @param e
|
||||
* the exception that caused the failure
|
||||
*/
|
||||
void onFailure(Exception e);
|
||||
}
|
||||
}
|
|
@ -10,60 +10,19 @@ import org.elasticsearch.cluster.service.ClusterService;
|
|||
import org.elasticsearch.common.io.stream.NamedWriteable;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
/**
|
||||
* Executes an action on an index related to its lifecycle.
|
||||
*/
|
||||
public interface LifecycleAction extends ToXContentObject, NamedWriteable {
|
||||
|
||||
/**
|
||||
* Checks the current state of the {@link LifecycleAction} and progresses
|
||||
* the action towards completion . Note that a {@link LifecycleAction} may
|
||||
* require multiple calls to this method before it is complete. Equally this
|
||||
* method may do nothing if it needs to wait for something to complete
|
||||
* before proceeding.
|
||||
*
|
||||
* @param index
|
||||
* the {@link Index} on which to perform the action.
|
||||
* @param client
|
||||
* the {@link Client} to use for making changes to the index.
|
||||
* @param listener
|
||||
* a {@link Listener} to call when this call completes.
|
||||
*/
|
||||
void execute(Index index, Client client, ClusterService clusterService, Listener listener);
|
||||
List<Step> toSteps(String phase, Index index, Client client, ThreadPool threadPool, LongSupplier nowSupplier);
|
||||
|
||||
default boolean indexSurvives() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* A callback for when a {@link LifecycleAction} finishes executing
|
||||
*/
|
||||
interface Listener {
|
||||
|
||||
/**
|
||||
* Called if the call to
|
||||
* {@link LifecycleAction#execute(Index, Client, ClusterService, Listener)}
|
||||
* was successful
|
||||
*
|
||||
* @param completed
|
||||
* <code>true</code> iff the {@link LifecycleAction} is now
|
||||
* complete and requires no more calls to
|
||||
* {@link LifecycleAction#execute(Index, Client, ClusterService, Listener)
|
||||
* execute(Index, Client, Listener)}.
|
||||
*/
|
||||
void onSuccess(boolean completed);
|
||||
|
||||
/**
|
||||
* Called if there was an exception during
|
||||
* {@link LifecycleAction#execute(Index, Client, ClusterService, Listener)}.
|
||||
* Note that even the call to
|
||||
* {@link LifecycleAction#execute(Index, Client, ClusterService, Listener)}
|
||||
* may be retried even after this method is called.
|
||||
*
|
||||
* @param e
|
||||
* the exception that caused the failure
|
||||
*/
|
||||
void onFailure(Exception e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,26 +6,33 @@
|
|||
package org.elasticsearch.xpack.core.indexlifecycle;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.AbstractDiffable;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
||||
import org.elasticsearch.cluster.Diffable;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.logging.ESLoggerFactory;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleContext.Listener;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
|
@ -78,7 +85,8 @@ public class LifecyclePolicy extends AbstractDiffable<LifecyclePolicy>
|
|||
}
|
||||
this.name = name;
|
||||
this.phases = phases;
|
||||
this.type.validate(phases.values());
|
||||
// TODO(talevy): return validation
|
||||
//this.type.validate(phases.values());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -136,48 +144,49 @@ public class LifecyclePolicy extends AbstractDiffable<LifecyclePolicy>
|
|||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the current state and executes the appropriate {@link Phase}.
|
||||
*
|
||||
* @param context
|
||||
* the {@link IndexLifecycleContext} to use to execute the
|
||||
* {@link LifecyclePolicy}.
|
||||
*/
|
||||
public void execute(IndexLifecycleContext context) {
|
||||
String currentPhaseName = context.getPhase();
|
||||
boolean currentPhaseActionsComplete = context.getAction().equals(Phase.PHASE_COMPLETED);
|
||||
String indexName = context.getLifecycleTarget();
|
||||
Phase currentPhase = phases.get(currentPhaseName);
|
||||
if (Strings.isNullOrEmpty(currentPhaseName) || currentPhaseActionsComplete) {
|
||||
Phase nextPhase = type.nextPhase(phases, currentPhase);
|
||||
// We only want to execute the phase if the conditions for executing are met (e.g. the index is old enough)
|
||||
if (nextPhase != null && context.canExecute(nextPhase)) {
|
||||
String nextPhaseName = nextPhase.getName();
|
||||
// Set the phase on the context to this phase so we know where we are next time we execute
|
||||
context.setPhase(nextPhaseName, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
logger.info("Successfully initialised phase [" + nextPhaseName + "] for index [" + indexName + "]");
|
||||
// We might as well execute the phase now rather than waiting for execute to be called again
|
||||
nextPhase.execute(context, type.getActionProvider(context, nextPhase));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
logger.error("Failed to initialised phase [" + nextPhaseName + "] for index [" + indexName + "]", e);
|
||||
}
|
||||
});
|
||||
public StepResult execute(List<Step> steps, ClusterState currentState, IndexMetaData indexMetaData, Client client, LongSupplier nowSupplier) {
|
||||
StepResult lastStepResult = null;
|
||||
ClusterState updatedState = currentState;
|
||||
for (int i = getNextStepIdx(steps, indexMetaData); i < steps.size(); i++) {
|
||||
lastStepResult = steps.get(i).execute(updatedState);
|
||||
if (lastStepResult.isComplete() && lastStepResult.indexSurvived()) {
|
||||
if (i < steps.size() - 1) {
|
||||
Step nextStep = steps.get(i + 1);
|
||||
long now = nowSupplier.getAsLong();
|
||||
// fetch details about next step to run and update the cluster state with this information
|
||||
Settings newLifecyclePhaseSettings = Settings.builder()
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE, nextStep.getPhase())
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE_TIME, now)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, now)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, nextStep.getAction())
|
||||
.put(LifecycleSettings.LIFECYCLE_STEP_TIME, now)
|
||||
.put(LifecycleSettings.LIFECYCLE_STEP, nextStep.getName())
|
||||
.build();
|
||||
updatedState = ClusterState.builder(lastStepResult.getClusterState())
|
||||
.metaData(MetaData.builder(lastStepResult.getClusterState().metaData())
|
||||
.updateSettings(newLifecyclePhaseSettings)).build();
|
||||
lastStepResult = new StepResult(lastStepResult, updatedState);
|
||||
}
|
||||
} else {
|
||||
// If we have already seen this index and the action is not PHASE_COMPLETED then we just need to execute the current phase again
|
||||
if (currentPhase == null) {
|
||||
throw new IllegalStateException("Current phase [" + currentPhaseName + "] not found in lifecycle ["
|
||||
+ getName() + "] for index [" + indexName + "]");
|
||||
} else {
|
||||
currentPhase.execute(context, type.getActionProvider(context, currentPhase));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return lastStepResult;
|
||||
}
|
||||
|
||||
private int getNextStepIdx(List<Step> steps, IndexMetaData indexMetaData) {
|
||||
String step = indexMetaData.getSettings().get(LifecycleSettings.LIFECYCLE_STEP);
|
||||
if (step == null) {
|
||||
return 0;
|
||||
}
|
||||
for (int i = 0; i < steps.size(); i++) {
|
||||
if (steps.get(i).getName().equals(step)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return steps.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -16,9 +16,11 @@ public class LifecycleSettings {
|
|||
public static final String LIFECYCLE_NAME = "index.lifecycle.name";
|
||||
public static final String LIFECYCLE_PHASE = "index.lifecycle.phase";
|
||||
public static final String LIFECYCLE_ACTION = "index.lifecycle.action";
|
||||
public static final String LIFECYCLE_STEP = "index.lifecycle.step";
|
||||
public static final String LIFECYCLE_INDEX_CREATION_DATE = "index.lifecycle.date";
|
||||
public static final String LIFECYCLE_PHASE_TIME = "index.lifecycle.phase_time";
|
||||
public static final String LIFECYCLE_ACTION_TIME = "index.lifecycle.action_time";
|
||||
public static final String LIFECYCLE_STEP_TIME = "index.lifecycle.step_time";
|
||||
|
||||
// NORELEASE: we should probably change the default to something other than three seconds for initial release
|
||||
public static final Setting<TimeValue> LIFECYCLE_POLL_INTERVAL_SETTING = Setting.positiveTimeSetting(LIFECYCLE_POLL_INTERVAL,
|
||||
|
@ -29,10 +31,14 @@ public class LifecycleSettings {
|
|||
Setting.Property.Dynamic, Setting.Property.IndexScope);
|
||||
public static final Setting<String> LIFECYCLE_ACTION_SETTING = Setting.simpleString(LIFECYCLE_ACTION,
|
||||
Setting.Property.Dynamic, Setting.Property.IndexScope);
|
||||
public static final Setting<String> LIFECYCLE_STEP_SETTING = Setting.simpleString(LIFECYCLE_ACTION,
|
||||
Setting.Property.Dynamic, Setting.Property.IndexScope);
|
||||
public static final Setting<Long> LIFECYCLE_INDEX_CREATION_DATE_SETTING = Setting.longSetting(LIFECYCLE_INDEX_CREATION_DATE,
|
||||
-1L, -1L, Setting.Property.Dynamic, Setting.Property.IndexScope);
|
||||
public static final Setting<Long> LIFECYCLE_PHASE_TIME_SETTING = Setting.longSetting(LIFECYCLE_PHASE_TIME,
|
||||
-1L, -1L, Setting.Property.Dynamic, Setting.Property.IndexScope);
|
||||
public static final Setting<Long> LIFECYCLE_ACTION_TIME_SETTING = Setting.longSetting(LIFECYCLE_ACTION_TIME,
|
||||
-1L, -1L, Setting.Property.Dynamic, Setting.Property.IndexScope);
|
||||
public static final Setting<Long> LIFECYCLE_STEP_TIME_SETTING = Setting.longSetting(LIFECYCLE_ACTION_TIME,
|
||||
-1L, -1L, Setting.Property.Dynamic, Setting.Property.IndexScope);
|
||||
}
|
||||
|
|
|
@ -47,14 +47,4 @@ public interface LifecycleType extends NamedWriteable {
|
|||
* @return the {@link LifecyclePolicy} type.
|
||||
*/
|
||||
String getType();
|
||||
|
||||
/**
|
||||
* @param context
|
||||
* the index lifecycle context for this phase at the time of
|
||||
* execution
|
||||
* @param phase
|
||||
* the current phase for which to provide an action provider
|
||||
* @return the action provider
|
||||
*/
|
||||
LifecyclePolicy.NextActionProvider getActionProvider(IndexLifecycleContext context, Phase phase);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
package org.elasticsearch.xpack.core.indexlifecycle;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
|
@ -18,13 +19,17 @@ import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
|
|||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleContext.Listener;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.TreeMap;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.elasticsearch.xpack.core.indexlifecycle.ObjectParserUtils.convertListToMapValues;
|
||||
|
||||
|
@ -131,126 +136,12 @@ public class Phase implements ToXContentObject, Writeable {
|
|||
return actions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the current state and executes the appropriate
|
||||
* {@link LifecycleAction}.
|
||||
*
|
||||
* @param context
|
||||
* the {@link IndexLifecycleContext} to use to execute the
|
||||
* {@link Phase}.
|
||||
* @param nextActionProvider
|
||||
* the next action provider
|
||||
*/
|
||||
protected void execute(IndexLifecycleContext context, LifecyclePolicy.NextActionProvider nextActionProvider) {
|
||||
String currentActionName = context.getAction();
|
||||
String indexName = context.getLifecycleTarget();
|
||||
if (Strings.isNullOrEmpty(currentActionName)) {
|
||||
// This is is the first time this phase has been called so get the first action and execute it.
|
||||
String firstActionName;
|
||||
LifecycleAction firstAction;
|
||||
if (actions.isEmpty()) {
|
||||
// There are no actions in this phase so use the PHASE_COMPLETE action name.
|
||||
firstAction = null;
|
||||
firstActionName = PHASE_COMPLETED;
|
||||
} else {
|
||||
firstAction = nextActionProvider.next(null);
|
||||
firstActionName = firstAction.getWriteableName();
|
||||
}
|
||||
// Set the action on the context to this first action so we know where we are next time we execute
|
||||
context.setAction(firstActionName, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
logger.info("Successfully initialised action [" + firstActionName + "] for index [" + indexName + "]");
|
||||
// Now execute the action unless its PHASE_COMPLETED
|
||||
if (firstActionName.equals(PHASE_COMPLETED) == false) {
|
||||
executeAction(context, indexName, firstAction, nextActionProvider);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
// Something went wrong so log the error and hopefully it will succeed next time execute
|
||||
// is called. NORELEASE can we do better here?
|
||||
logger.error("Failed to initialised action [" + firstActionName + "] for index [" + indexName + "]", e);
|
||||
}
|
||||
});
|
||||
} else if (currentActionName.equals(PHASE_COMPLETED) == false) {
|
||||
// We have an action name and its not PHASE COMPLETED so we need to execute the action
|
||||
// First find the action in the actions map.
|
||||
if (actions.containsKey(currentActionName) == false) {
|
||||
throw new IllegalStateException("Current action [" + currentActionName + "] not found in phase ["
|
||||
+ getName() + "] for index [" + indexName + "]");
|
||||
}
|
||||
LifecycleAction currentAction = actions.get(currentActionName);
|
||||
// then execute the action
|
||||
executeAction(context, indexName, currentAction, nextActionProvider);
|
||||
}
|
||||
}
|
||||
|
||||
private void executeAction(IndexLifecycleContext context, String indexName, LifecycleAction action,
|
||||
LifecyclePolicy.NextActionProvider nextActionProvider) {
|
||||
String actionName = action.getWriteableName();
|
||||
context.executeAction(action, new LifecycleAction.Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
if (completed) {
|
||||
// Since we completed the current action move to the next
|
||||
// action if the index survives this action
|
||||
if (action.indexSurvives()) {
|
||||
logger.info("Action [" + actionName + "] for index [" + indexName + "] complete, moving to next action");
|
||||
moveToNextAction(context, indexName, action, nextActionProvider);
|
||||
} else {
|
||||
logger.info("Action [" + actionName + "] for index [" + indexName + "] complete");
|
||||
}
|
||||
} else {
|
||||
logger.info("Action [" + actionName + "] for index [" + indexName + "] executed sucessfully but is not yet complete");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
logger.info("Action [" + actionName + "] for index [" + indexName + "] failed", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void moveToNextAction(IndexLifecycleContext context, String indexName, LifecycleAction currentAction,
|
||||
LifecyclePolicy.NextActionProvider nextActionProvider) {
|
||||
LifecycleAction nextAction = nextActionProvider.next(currentAction);
|
||||
if (nextAction != null) {
|
||||
context.setAction(nextAction.getWriteableName(), new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
logger.info("Successfully initialised action [" + nextAction.getWriteableName() + "] in phase [" + getName()
|
||||
+ "] for index [" + indexName + "]");
|
||||
// We might as well execute the new action now rather than waiting for execute to be called again
|
||||
execute(context, nextActionProvider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
logger.error("Failed to initialised action [" + nextAction.getWriteableName() + "] in phase [" + getName()
|
||||
+ "] for index [" + indexName + "]", e);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// There is no next action so set the action to PHASE_COMPLETED
|
||||
context.setAction(Phase.PHASE_COMPLETED, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
logger.info("Successfully completed phase [" + getName() + "] for index [" + indexName + "]");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
logger.error("Failed to complete phase [" + getName() + "] for index [" + indexName + "]", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
public List<Step> toSteps(Index index, long indexLifecycleCreationDate, Client client, ThreadPool threadPool, LongSupplier nowSupplier) {
|
||||
// TODO(talevy) phase needs to know indexLifecycleStartTime
|
||||
PhaseAfterStep phaseAfterStep = new PhaseAfterStep(threadPool, indexLifecycleCreationDate, nowSupplier, after,
|
||||
"phase_start", index.getName(), getName(), null);
|
||||
return Stream.concat(Stream.of(phaseAfterStep), actions.values().stream()
|
||||
.flatMap(a -> a.toSteps(name, index, client, threadPool, nowSupplier).stream())).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Step;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.StepResult;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.BooleanSupplier;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
public class PhaseAfterStep extends Step {
|
||||
private final CompletableFuture<StepResult> timeUp;
|
||||
private final ThreadPool threadPool;
|
||||
private final long indexCreationDate;
|
||||
private final LongSupplier nowSupplier;
|
||||
private final TimeValue after;
|
||||
|
||||
public PhaseAfterStep(ThreadPool threadPool, long indexCreationDate, LongSupplier nowSupplier, TimeValue after, String name,
|
||||
String index, String phase, String action) {
|
||||
super(name, action, phase, index);
|
||||
this.threadPool = threadPool;
|
||||
this.indexCreationDate = indexCreationDate;
|
||||
this.nowSupplier = nowSupplier;
|
||||
this.timeUp = new CompletableFuture<>();
|
||||
this.after = after;
|
||||
}
|
||||
|
||||
public StepResult execute(ClusterState currentState) {
|
||||
LongSupplier elapsed = () -> nowSupplier.getAsLong() - indexCreationDate;
|
||||
BooleanSupplier isReady = () -> after.getSeconds() <= elapsed.getAsLong();
|
||||
if (isReady.getAsBoolean()) {
|
||||
return new StepResult("phase starting", null, currentState, true, true);
|
||||
} else {
|
||||
threadPool.schedule(TimeValue.timeValueSeconds(elapsed.getAsLong()), ThreadPool.Names.GENERIC, () -> {
|
||||
if (after.getSeconds() <= elapsed.getAsLong()) {
|
||||
// IndexLifecycleService.triggerPolicies()
|
||||
}
|
||||
});
|
||||
return new StepResult("phase-check-rescheduled", null, currentState, true, false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -10,7 +10,9 @@ import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest
|
|||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
|
||||
import org.elasticsearch.action.support.ActiveShardCount;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.Strings;
|
||||
|
@ -21,9 +23,13 @@ import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
import static org.elasticsearch.common.xcontent.ConstructingObjectParser.constructorArg;
|
||||
|
||||
|
@ -77,28 +83,14 @@ public class ReplicasAction implements LifecycleAction {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void execute(Index index, Client client, ClusterService clusterService, Listener listener) {
|
||||
IndexMetaData idxMeta = clusterService.state().metaData().getIndexSafe(index);
|
||||
int currentNumberReplicas = idxMeta.getNumberOfReplicas();
|
||||
if (currentNumberReplicas == numberOfReplicas) {
|
||||
boolean isAllocationCompleted = ActiveShardCount.ALL.enoughShardsActive(clusterService.state(), index.getName());
|
||||
listener.onSuccess(isAllocationCompleted);
|
||||
} else {
|
||||
UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(index.getName())
|
||||
.settings(Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, numberOfReplicas));
|
||||
client.admin().indices().updateSettings(updateSettingsRequest, new ActionListener<UpdateSettingsResponse>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(UpdateSettingsResponse response) {
|
||||
listener.onSuccess(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
listener.onFailure(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
public List<Step> toSteps(String phase, Index index, Client client, ThreadPool threadPool, LongSupplier nowSupplier) {
|
||||
ClusterStateUpdateStep updateAllocationSettings = new ClusterStateUpdateStep(
|
||||
"update_replica_count", NAME, phase, index.getName(), (currentState) ->
|
||||
ClusterState.builder(currentState).metaData(MetaData.builder(currentState.metaData())
|
||||
.updateNumberOfReplicas(numberOfReplicas, index.getName())).build());
|
||||
ConditionalWaitStep isReplicatedCheck = new ConditionalWaitStep("wait_replicas_allocated", NAME,
|
||||
phase, index.getName(), (currentState) -> ActiveShardCount.ALL.enoughShardsActive(currentState, index.getName()) );
|
||||
return Arrays.asList(updateAllocationSettings, isReplicatedCheck);
|
||||
}
|
||||
|
||||
public int getNumberOfReplicas() {
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
package org.elasticsearch.xpack.core.indexlifecycle;
|
||||
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.elasticsearch.ExceptionsHelper;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverRequest;
|
||||
import org.elasticsearch.action.admin.indices.rollover.RolloverResponse;
|
||||
|
@ -24,9 +23,13 @@ import org.elasticsearch.common.xcontent.ObjectParser.ValueType;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
/**
|
||||
* A {@link LifecycleAction} which deletes the index.
|
||||
|
@ -150,32 +153,38 @@ public class RolloverAction implements LifecycleAction {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void execute(Index index, Client client, ClusterService clusterService, Listener listener) {
|
||||
if (clusterService.state().getMetaData().index(index.getName()).getAliases().containsKey(alias)) {
|
||||
RolloverRequest rolloverRequest = new RolloverRequest(alias, null);
|
||||
if (maxAge != null) {
|
||||
rolloverRequest.addMaxIndexAgeCondition(maxAge);
|
||||
}
|
||||
if (maxSize != null) {
|
||||
rolloverRequest.addMaxIndexSizeCondition(maxSize);
|
||||
}
|
||||
if (maxDocs != null) {
|
||||
rolloverRequest.addMaxIndexDocsCondition(maxDocs);
|
||||
}
|
||||
client.admin().indices().rolloverIndex(rolloverRequest, new ActionListener<RolloverResponse>() {
|
||||
@Override
|
||||
public void onResponse(RolloverResponse rolloverResponse) {
|
||||
listener.onSuccess(rolloverResponse.isRolledOver());
|
||||
}
|
||||
public List<Step> toSteps(String phase, Index index, Client client, ThreadPool threadPool, LongSupplier nowSupplier) {
|
||||
return Collections.emptyList();
|
||||
// ConditionalWaitStep wait = new ConditionalWaitStep(clusterService, "wait_for_rollover", index.getName(), phase, action, (clusterState) -> {
|
||||
// // TODO(talevy): actually, needs to RolloverRequest with dryrun to get the appropriate data; clusterState is not enough...
|
||||
// // can potentially reduce down to original problem with RolloverRequest...1minute...RolloverRequest...1minute... probably ok?
|
||||
// if (clusterService.state().getMetaData().index(index.getName()).getAliases().containsKey(alias)) {
|
||||
// RolloverRequest rolloverRequest = new RolloverRequest(alias, null);
|
||||
// if (maxAge != null) {
|
||||
// rolloverRequest.addMaxIndexAgeCondition(maxAge);
|
||||
// }
|
||||
// if (maxSize != null) {
|
||||
// rolloverRequest.addMaxIndexSizeCondition(maxSize);
|
||||
// }
|
||||
// if (maxDocs != null) {
|
||||
// rolloverRequest.addMaxIndexDocsCondition(maxDocs);
|
||||
// }
|
||||
// client.admin().indices().rolloverIndex(rolloverRequest, new ActionListener<RolloverResponse>() {
|
||||
// @Override
|
||||
// public void onResponse(RolloverResponse rolloverResponse) {
|
||||
// return rolloverResponse.isRolledOver();
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// listener.onFailure(e);
|
||||
// }
|
||||
// });
|
||||
// } else {
|
||||
// listener.onSuccess(true);
|
||||
// }
|
||||
// });
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
listener.onFailure(e);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
listener.onSuccess(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -10,27 +10,39 @@ import org.elasticsearch.action.ActionListener;
|
|||
import org.elasticsearch.action.admin.indices.alias.Alias;
|
||||
import org.elasticsearch.action.admin.indices.alias.IndicesAliasesRequest;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
|
||||
import org.elasticsearch.action.admin.indices.create.CreateIndexRequestBuilder;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequest;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeRequestBuilder;
|
||||
import org.elasticsearch.action.admin.indices.shrink.ResizeResponse;
|
||||
import org.elasticsearch.action.support.ActiveShardCount;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.AliasMetaData;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.routing.allocation.decider.AllocationDeciders;
|
||||
import org.elasticsearch.cluster.routing.allocation.decider.FilterAllocationDecider;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.Strings;
|
||||
import org.elasticsearch.common.io.stream.StreamInput;
|
||||
import org.elasticsearch.common.io.stream.StreamOutput;
|
||||
import org.elasticsearch.common.logging.ESLoggerFactory;
|
||||
import org.elasticsearch.common.settings.ClusterSettings;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
/**
|
||||
* A {@link LifecycleAction} which shrinks the index.
|
||||
|
@ -49,6 +61,7 @@ public class ShrinkAction implements LifecycleAction {
|
|||
}
|
||||
|
||||
private int numberOfShards;
|
||||
private AllocationDeciders allocationDeciders;
|
||||
|
||||
public static ShrinkAction parse(XContentParser parser) throws IOException {
|
||||
return PARSER.parse(parser, new CreateIndexRequest());
|
||||
|
@ -59,6 +72,9 @@ public class ShrinkAction implements LifecycleAction {
|
|||
throw new IllegalArgumentException("[" + NUMBER_OF_SHARDS_FIELD.getPreferredName() + "] must be greater than 0");
|
||||
}
|
||||
this.numberOfShards = numberOfShards;
|
||||
FilterAllocationDecider decider = new FilterAllocationDecider(Settings.EMPTY,
|
||||
new ClusterSettings(Settings.EMPTY, ClusterSettings.BUILT_IN_CLUSTER_SETTINGS));
|
||||
this.allocationDeciders = new AllocationDeciders(Settings.EMPTY, Collections.singletonList(decider));
|
||||
}
|
||||
|
||||
public ShrinkAction(StreamInput in) throws IOException {
|
||||
|
@ -87,103 +103,85 @@ public class ShrinkAction implements LifecycleAction {
|
|||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the Shrink Action.
|
||||
*
|
||||
* This function first checks whether the target shrunk index exists already, if it does not, then
|
||||
* it will set the index to read-only and issue a resize request.
|
||||
*
|
||||
* Since the shrink response is not returned after a successful shrunk operation, we must poll to see if
|
||||
* all the shards of the newly shrunk index are initialized. If so, then we can return the index to read-write
|
||||
* and tell the listener that we have completed the action.
|
||||
*
|
||||
* @param index
|
||||
* the {@link Index} on which to perform the action.
|
||||
* @param client
|
||||
* the {@link Client} to use for making changes to the index.
|
||||
* @param clusterService
|
||||
* the {@link ClusterService} to retrieve the current cluster state from.
|
||||
* @param listener
|
||||
* the {@link LifecycleAction.Listener} to return completion or failure responses to.
|
||||
*/
|
||||
@Override
|
||||
public void execute(Index index, Client client, ClusterService clusterService, Listener listener) {
|
||||
String targetIndexName = SHRUNK_INDEX_NAME_PREFIX + index.getName();
|
||||
ClusterState clusterState = clusterService.state();
|
||||
IndexMetaData indexMetaData = clusterState.metaData().index(index.getName());
|
||||
String sourceIndexName = IndexMetaData.INDEX_SHRINK_SOURCE_NAME.get(indexMetaData.getSettings());
|
||||
boolean isShrunkIndex = index.getName().equals(SHRUNK_INDEX_NAME_PREFIX + sourceIndexName);
|
||||
IndexMetaData shrunkIndexMetaData = clusterState.metaData().index(targetIndexName);
|
||||
if (isShrunkIndex) {
|
||||
// We are currently managing the shrunken index. This means all previous operations were successful and
|
||||
// the original index is deleted. It is important to add an alias from the original index name to the shrunken
|
||||
// index so that previous actions will still succeed.
|
||||
boolean aliasAlreadyExists = indexMetaData.getAliases().values().contains(AliasMetaData.builder(sourceIndexName).build());
|
||||
boolean sourceIndexDeleted = clusterState.metaData().hasIndex(sourceIndexName) == false;
|
||||
if (sourceIndexDeleted && aliasAlreadyExists) {
|
||||
listener.onSuccess(true);
|
||||
} else {
|
||||
IndicesAliasesRequest aliasesRequest = new IndicesAliasesRequest()
|
||||
.addAliasAction(IndicesAliasesRequest.AliasActions.removeIndex().index(sourceIndexName))
|
||||
.addAliasAction(IndicesAliasesRequest.AliasActions.add().index(index.getName()).alias(sourceIndexName));
|
||||
client.admin().indices().aliases(aliasesRequest, ActionListener.wrap(response -> {
|
||||
listener.onSuccess(true);
|
||||
}, listener::onFailure));
|
||||
public List<Step> toSteps(String phase, Index index, Client client, ThreadPool threadPool, LongSupplier nowSupplier) {
|
||||
String shrunkenIndexName = SHRUNK_INDEX_NAME_PREFIX + index.getName();
|
||||
// TODO(talevy): magical node.name to allocate to
|
||||
String nodeName = "MAGIC";
|
||||
ClusterStateUpdateStep updateAllocationToOneNode = new ClusterStateUpdateStep(
|
||||
"move_to_single_node", NAME, phase, index.getName(), (clusterState) -> {
|
||||
IndexMetaData idxMeta = clusterState.metaData().index(index);
|
||||
if (idxMeta == null) {
|
||||
return clusterState;
|
||||
}
|
||||
} else if (shrunkIndexMetaData == null) {
|
||||
// Shrunken index is not present yet, it is time to issue to shrink request
|
||||
ResizeRequest resizeRequest = new ResizeRequest(targetIndexName, index.getName());
|
||||
resizeRequest.getTargetIndexRequest().settings(Settings.builder()
|
||||
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, numberOfShards)
|
||||
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, indexMetaData.getNumberOfReplicas())
|
||||
.put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, indexMetaData.getCreationDate())
|
||||
.build());
|
||||
indexMetaData.getAliases().values().spliterator().forEachRemaining(aliasMetaDataObjectCursor -> {
|
||||
resizeRequest.getTargetIndexRequest().alias(new Alias(aliasMetaDataObjectCursor.value.alias()));
|
||||
Settings.Builder newSettings = Settings.builder()
|
||||
.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_PREFIX, "")
|
||||
.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_PREFIX, "")
|
||||
.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + "_name", nodeName);
|
||||
return ClusterState.builder(clusterState)
|
||||
.metaData(MetaData.builder(clusterState.metaData())
|
||||
.updateSettings(newSettings.build(), index.getName())).build();
|
||||
});
|
||||
UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(Settings.builder()
|
||||
.put(IndexMetaData.SETTING_BLOCKS_WRITE, true).build(), index.getName());
|
||||
client.admin().indices().updateSettings(updateSettingsRequest, ActionListener.wrap(r -> {
|
||||
client.admin().indices().resizeIndex(resizeRequest, ActionListener.wrap(
|
||||
resizeResponse -> {
|
||||
if (resizeResponse.isAcknowledged()) {
|
||||
listener.onSuccess(false);
|
||||
} else {
|
||||
listener.onFailure(new IllegalStateException("Shrink request failed to be acknowledged"));
|
||||
}
|
||||
}, listener::onFailure));
|
||||
}, listener::onFailure));
|
||||
} else if (index.getName().equals(IndexMetaData.INDEX_SHRINK_SOURCE_NAME.get(shrunkIndexMetaData.getSettings())) == false) {
|
||||
// The target shrunken index exists, but it was not shrunk from our managed index. This means
|
||||
// some external actions were done to create this index, and so we cannot progress with the shrink
|
||||
// action until this is resolved.
|
||||
listener.onFailure(new IllegalStateException("Cannot shrink index [" + index.getName() + "] because target " +
|
||||
"index [" + targetIndexName + "] already exists."));
|
||||
} else if (ActiveShardCount.ALL.enoughShardsActive(clusterService.state(), targetIndexName)) {
|
||||
if (indexMetaData.getSettings().get(LifecycleSettings.LIFECYCLE_NAME)
|
||||
.equals(shrunkIndexMetaData.getSettings().get(LifecycleSettings.LIFECYCLE_NAME))) {
|
||||
// Since both the shrunken and original indices co-exist, do nothing and wait until
|
||||
// the final step of the shrink action is completed and this original index is deleted.
|
||||
listener.onSuccess(false);
|
||||
} else {
|
||||
// Since all shards of the shrunken index are active, it is safe to continue forward
|
||||
// and begin swapping the indices by inheriting the lifecycle management to the new shrunken index.
|
||||
UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(Settings.builder()
|
||||
.put(LifecycleSettings.LIFECYCLE_NAME, indexMetaData.getSettings().get(LifecycleSettings.LIFECYCLE_NAME))
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE, indexMetaData.getSettings().get(LifecycleSettings.LIFECYCLE_PHASE))
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, indexMetaData.getSettings().get(LifecycleSettings.LIFECYCLE_ACTION))
|
||||
.build(), targetIndexName);
|
||||
client.admin().indices().updateSettings(updateSettingsRequest,
|
||||
ActionListener.wrap(r -> listener.onSuccess(false), listener::onFailure));
|
||||
}
|
||||
} else {
|
||||
// We are here because both the shrunken and original indices exist, but the shrunken index is not
|
||||
// fully active yet. This means that we wait for another poll iteration of execute to check the
|
||||
// state again.
|
||||
logger.debug("index [" + index.getName() + "] has been shrunk to shrunken-index [" + targetIndexName + "], but" +
|
||||
"shrunken index is not fully active yet");
|
||||
listener.onSuccess(false);
|
||||
|
||||
// resizeRequest.getTargetIndexRequest().settings(Settings.builder()
|
||||
// .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, numberOfShards)
|
||||
// .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, indexMetaData.getNumberOfReplicas())
|
||||
// .put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, indexMetaData.getCreationDate())
|
||||
// .build());
|
||||
// indexMetaData.getAliases().values().spliterator().forEachRemaining(aliasMetaDataObjectCursor -> {
|
||||
// resizeRequest.getTargetIndexRequest().alias(new Alias(aliasMetaDataObjectCursor.value.alias()));
|
||||
// });
|
||||
|
||||
// TODO(talevy): needs access to original index metadata, not just Index
|
||||
int numReplicas = -1;
|
||||
long lifecycleDate = -1L;
|
||||
Settings targetIndexSettings = Settings.builder()
|
||||
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, numberOfShards)
|
||||
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, numReplicas)
|
||||
.put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, lifecycleDate)
|
||||
.build();
|
||||
CreateIndexRequest targetIndexRequest = new CreateIndexRequest(shrunkenIndexName, targetIndexSettings);
|
||||
// TODO(talevy): need access to indexmetadata
|
||||
// indexMetaData.getAliases().values().spliterator().forEachRemaining(aliasMetaDataObjectCursor -> {
|
||||
// resizeRequest.getTargetIndexRequest().alias(new Alias(aliasMetaDataObjectCursor.value.alias()));
|
||||
// });
|
||||
|
||||
ClientStep<ResizeRequestBuilder, ResizeResponse> shrinkStep = new ClientStep<>( "segment_count",
|
||||
NAME, phase, index.getName(),
|
||||
|
||||
client.admin().indices().prepareResizeIndex(index.getName(), shrunkenIndexName).setTargetIndex(targetIndexRequest),
|
||||
currentState -> {
|
||||
// check that shrunken index was already created, if so, no need to both client
|
||||
IndexMetaData shrunkMetaData = currentState.metaData().index(shrunkenIndexName);
|
||||
boolean isSuccessful = shrunkMetaData != null && shrunkenIndexName.equals(IndexMetaData.INDEX_SHRINK_SOURCE_NAME
|
||||
.get(shrunkMetaData.getSettings()));
|
||||
|
||||
}, ResizeResponse::isAcknowledged);
|
||||
|
||||
|
||||
ConditionalWaitStep shrunkenIndexIsAllocated = new ConditionalWaitStep("wait_replicas_allocated", NAME,
|
||||
phase, index.getName(), (currentState) -> ActiveShardCount.ALL.enoughShardsActive(currentState, index.getName()) );
|
||||
|
||||
ClusterStateUpdateStep deleteAndUpdateAliases = new ClusterStateUpdateStep(
|
||||
"delete_this_index_set_aliases_on_shrunken", NAME, phase, index.getName(), (clusterState) -> {
|
||||
IndexMetaData idxMeta = clusterState.metaData().index(index);
|
||||
if (idxMeta == null) {
|
||||
return clusterState;
|
||||
}
|
||||
|
||||
// TODO(talevy): expose - MetadataDeleteIndexService.deleteIndices(clusterState, Set.of(index.getName()))
|
||||
// also, looks like deletes are special CS tasks
|
||||
// AckedClusterStateUpdateTask, Priority.URGENT
|
||||
|
||||
// 1. delete index
|
||||
// 2. assign alias to shrunken index
|
||||
// 3. assign index.lifecycle settings to shrunken index
|
||||
return clusterState;
|
||||
});
|
||||
|
||||
return Arrays.asList(updateAllocationToOneNode,
|
||||
AllocateAction.getAllocationCheck(allocationDeciders, phase, index.getName()),
|
||||
shrinkStep, shrunkenIndexIsAllocated, deleteAndUpdateAliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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.core.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
|
||||
/**
|
||||
* A {@link LifecycleAction} which deletes the index.
|
||||
*/
|
||||
public abstract class Step {
|
||||
private final String name;
|
||||
private final String action;
|
||||
private final String phase;
|
||||
private final String index;
|
||||
|
||||
public Step(String name, String action, String phase, String index) {
|
||||
this.name = name;
|
||||
this.action = action;
|
||||
this.phase = phase;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public String getPhase() {
|
||||
return phase;
|
||||
}
|
||||
|
||||
public String getIndex() {
|
||||
return index;
|
||||
}
|
||||
|
||||
public abstract StepResult execute(ClusterState currentState);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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.indexlifecycle;
|
||||
|
||||
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
|
||||
public class StepResult {
|
||||
private final String message;
|
||||
private final Exception exception;
|
||||
private final ClusterState clusterState;
|
||||
private final boolean complete;
|
||||
private final boolean indexSurvived;
|
||||
|
||||
public StepResult(String message, Exception exception, ClusterState clusterState, boolean indexSurvived, boolean complete) {
|
||||
this.message = message;
|
||||
this.exception = exception;
|
||||
this.clusterState = clusterState;
|
||||
this.indexSurvived = indexSurvived;
|
||||
this.complete = complete;
|
||||
}
|
||||
|
||||
public StepResult(StepResult result, ClusterState newClusterState) {
|
||||
this(result.getMessage(), result.getException(), newClusterState, result.indexSurvived(), result.isComplete());
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public Exception getException() {
|
||||
return exception;
|
||||
}
|
||||
|
||||
public ClusterState getClusterState() {
|
||||
return clusterState;
|
||||
}
|
||||
|
||||
public boolean indexSurvived() {
|
||||
return indexSurvived;
|
||||
}
|
||||
|
||||
public boolean isComplete() {
|
||||
return complete;
|
||||
}
|
||||
}
|
|
@ -91,103 +91,103 @@ public class TimeseriesLifecycleType implements LifecycleType {
|
|||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This action provider returns an ordering for the actions within each of the four timeseries phases.
|
||||
* Hot Phase:
|
||||
* The Hot Phase only supports the {@link RolloverAction} and so that is the only action to order
|
||||
* Warm Phase:
|
||||
* The Warm Phase executes the supported actions in a slightly complicated order for the sake of
|
||||
* optimization. Assuming the {@link ReplicasAction} is specified, it will run first or last depending
|
||||
* on whether it increases, decreases, or keeps the existing replica count. If number-of-replicas is
|
||||
* kept the same, or reduced, then {@link ReplicasAction} is executed first, otherwise, it is last.
|
||||
* So the ordering looks something like this:
|
||||
* - {@link ReplicasAction} (if action.number_of_replicas lte idxMeta.number_of_replicas)
|
||||
* - {@link AllocateAction}
|
||||
* - {@link ShrinkAction}
|
||||
* - {@link ForceMergeAction}
|
||||
* - {@link ReplicasAction} (if action.number_of_replicas gt idxMeta.number_of_replicas)
|
||||
*
|
||||
* NORELEASE: there may exist further optimizations to this when {@link ShrinkAction} is specified.
|
||||
*
|
||||
* @param context the index lifecycle context for this phase at the time of execution
|
||||
* @param phase the current phase for which to provide an action provider
|
||||
* @return the {@link LifecyclePolicy.NextActionProvider} for {@code phase}.
|
||||
*/
|
||||
@Override
|
||||
public LifecyclePolicy.NextActionProvider getActionProvider(IndexLifecycleContext context, Phase phase) {
|
||||
Map<String, LifecycleAction> actions = phase.getActions();
|
||||
switch (phase.getName()) {
|
||||
case "hot":
|
||||
// The hot-phase only has one action, either start with it, or return null. Simple as that!
|
||||
return (action) -> (action == null) ? actions.getOrDefault(RolloverAction.NAME, null) : null;
|
||||
case "warm":
|
||||
return (action) -> {
|
||||
ReplicasAction replicasAction = (ReplicasAction) actions.getOrDefault(ReplicasAction.NAME, null);
|
||||
boolean replicaActionFirst = replicasAction != null
|
||||
&& replicasAction.getNumberOfReplicas() <= context.getNumberOfReplicas();
|
||||
if (action == null) {
|
||||
if (replicaActionFirst) {
|
||||
return replicasAction;
|
||||
}
|
||||
return Stream.of(AllocateAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME, ReplicasAction.NAME)
|
||||
.map(a -> actions.getOrDefault(a, null))
|
||||
.filter(Objects::nonNull).findFirst().orElse(null);
|
||||
} else if (action instanceof ReplicasAction) {
|
||||
if (replicaActionFirst) {
|
||||
return Stream.of(AllocateAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME)
|
||||
.map(a -> actions.getOrDefault(a, null))
|
||||
.filter(Objects::nonNull).findFirst().orElse(null);
|
||||
}
|
||||
} else if (action instanceof AllocateAction) {
|
||||
return Stream.of(ShrinkAction.NAME, ForceMergeAction.NAME, ReplicasAction.NAME)
|
||||
.map(a -> actions.getOrDefault(a, null))
|
||||
.filter(Objects::nonNull).findFirst().orElse(null);
|
||||
} else if (action instanceof ShrinkAction) {
|
||||
return Stream.of(ForceMergeAction.NAME, ReplicasAction.NAME)
|
||||
.map(a -> actions.getOrDefault(a, null))
|
||||
.filter(Objects::nonNull).findFirst().orElse(null);
|
||||
} else if (action instanceof ForceMergeAction) {
|
||||
if (replicaActionFirst == false) {
|
||||
return replicasAction;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
case "cold":
|
||||
return (action) -> {
|
||||
ReplicasAction replicasAction = (ReplicasAction) actions.getOrDefault(ReplicasAction.NAME, null);
|
||||
LifecycleAction allocateAction = actions.getOrDefault(AllocateAction.NAME, null);
|
||||
boolean replicaActionFirst = replicasAction != null
|
||||
&& replicasAction.getNumberOfReplicas() <= context.getNumberOfReplicas();
|
||||
if (action == null) {
|
||||
if (replicaActionFirst) {
|
||||
return replicasAction;
|
||||
} else if (allocateAction != null) {
|
||||
return allocateAction;
|
||||
}
|
||||
return replicasAction;
|
||||
} else if (action instanceof ReplicasAction) {
|
||||
if (replicaActionFirst) {
|
||||
return allocateAction;
|
||||
}
|
||||
} else if (action instanceof AllocateAction) {
|
||||
if (replicaActionFirst == false) {
|
||||
return replicasAction;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
case "delete":
|
||||
return (action) -> {
|
||||
if (action == null) {
|
||||
return actions.getOrDefault(DeleteAction.NAME, null);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
default:
|
||||
throw new IllegalArgumentException("phase [" + phase.getName() + "] is invalid for policy [timeseries]");
|
||||
}
|
||||
}
|
||||
// /**
|
||||
// * This action provider returns an ordering for the actions within each of the four timeseries phases.
|
||||
// * Hot Phase:
|
||||
// * The Hot Phase only supports the {@link RolloverAction} and so that is the only action to order
|
||||
// * Warm Phase:
|
||||
// * The Warm Phase executes the supported actions in a slightly complicated order for the sake of
|
||||
// * optimization. Assuming the {@link ReplicasAction} is specified, it will run first or last depending
|
||||
// * on whether it increases, decreases, or keeps the existing replica count. If number-of-replicas is
|
||||
// * kept the same, or reduced, then {@link ReplicasAction} is executed first, otherwise, it is last.
|
||||
// * So the ordering looks something like this:
|
||||
// * - {@link ReplicasAction} (if action.number_of_replicas lte idxMeta.number_of_replicas)
|
||||
// * - {@link AllocateAction}
|
||||
// * - {@link ShrinkAction}
|
||||
// * - {@link ForceMergeAction}
|
||||
// * - {@link ReplicasAction} (if action.number_of_replicas gt idxMeta.number_of_replicas)
|
||||
// *
|
||||
// * NORELEASE: there may exist further optimizations to this when {@link ShrinkAction} is specified.
|
||||
// *
|
||||
// * @param context the index lifecycle context for this phase at the time of execution
|
||||
// * @param phase the current phase for which to provide an action provider
|
||||
// * @return the {@link LifecyclePolicy.NextActionProvider} for {@code phase}.
|
||||
// */
|
||||
// @Override
|
||||
// public LifecyclePolicy.NextActionProvider getActionProvider(IndexLifecycleContext context, Phase phase) {
|
||||
// Map<String, LifecycleAction> actions = phase.getActions();
|
||||
// switch (phase.getName()) {
|
||||
// case "hot":
|
||||
// // The hot-phase only has one action, either start with it, or return null. Simple as that!
|
||||
// return (action) -> (action == null) ? actions.getOrDefault(RolloverAction.NAME, null) : null;
|
||||
// case "warm":
|
||||
// return (action) -> {
|
||||
// ReplicasAction replicasAction = (ReplicasAction) actions.getOrDefault(ReplicasAction.NAME, null);
|
||||
// boolean replicaActionFirst = replicasAction != null
|
||||
// && replicasAction.getNumberOfReplicas() <= context.getNumberOfReplicas();
|
||||
// if (action == null) {
|
||||
// if (replicaActionFirst) {
|
||||
// return replicasAction;
|
||||
// }
|
||||
// return Stream.of(AllocateAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME, ReplicasAction.NAME)
|
||||
// .map(a -> actions.getOrDefault(a, null))
|
||||
// .filter(Objects::nonNull).findFirst().orElse(null);
|
||||
// } else if (action instanceof ReplicasAction) {
|
||||
// if (replicaActionFirst) {
|
||||
// return Stream.of(AllocateAction.NAME, ShrinkAction.NAME, ForceMergeAction.NAME)
|
||||
// .map(a -> actions.getOrDefault(a, null))
|
||||
// .filter(Objects::nonNull).findFirst().orElse(null);
|
||||
// }
|
||||
// } else if (action instanceof AllocateAction) {
|
||||
// return Stream.of(ShrinkAction.NAME, ForceMergeAction.NAME, ReplicasAction.NAME)
|
||||
// .map(a -> actions.getOrDefault(a, null))
|
||||
// .filter(Objects::nonNull).findFirst().orElse(null);
|
||||
// } else if (action instanceof ShrinkAction) {
|
||||
// return Stream.of(ForceMergeAction.NAME, ReplicasAction.NAME)
|
||||
// .map(a -> actions.getOrDefault(a, null))
|
||||
// .filter(Objects::nonNull).findFirst().orElse(null);
|
||||
// } else if (action instanceof ForceMergeAction) {
|
||||
// if (replicaActionFirst == false) {
|
||||
// return replicasAction;
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// };
|
||||
// case "cold":
|
||||
// return (action) -> {
|
||||
// ReplicasAction replicasAction = (ReplicasAction) actions.getOrDefault(ReplicasAction.NAME, null);
|
||||
// LifecycleAction allocateAction = actions.getOrDefault(AllocateAction.NAME, null);
|
||||
// boolean replicaActionFirst = replicasAction != null
|
||||
// && replicasAction.getNumberOfReplicas() <= context.getNumberOfReplicas();
|
||||
// if (action == null) {
|
||||
// if (replicaActionFirst) {
|
||||
// return replicasAction;
|
||||
// } else if (allocateAction != null) {
|
||||
// return allocateAction;
|
||||
// }
|
||||
// return replicasAction;
|
||||
// } else if (action instanceof ReplicasAction) {
|
||||
// if (replicaActionFirst) {
|
||||
// return allocateAction;
|
||||
// }
|
||||
// } else if (action instanceof AllocateAction) {
|
||||
// if (replicaActionFirst == false) {
|
||||
// return replicasAction;
|
||||
// }
|
||||
// }
|
||||
// return null;
|
||||
// };
|
||||
// case "delete":
|
||||
// return (action) -> {
|
||||
// if (action == null) {
|
||||
// return actions.getOrDefault(DeleteAction.NAME, null);
|
||||
// }
|
||||
// return null;
|
||||
// };
|
||||
// default:
|
||||
// throw new IllegalArgumentException("phase [" + phase.getName() + "] is invalid for policy [timeseries]");
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void validate(Collection<Phase> phases) {
|
||||
|
|
|
@ -31,7 +31,6 @@ import org.elasticsearch.index.IndexNotFoundException;
|
|||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.node.Node;
|
||||
import org.elasticsearch.test.AbstractSerializingTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction.Listener;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
|
@ -113,368 +112,368 @@ public class AllocateActionTests extends AbstractSerializingTestCase<AllocateAct
|
|||
+ "must contain attributes for action " + AllocateAction.NAME, exception.getMessage());
|
||||
}
|
||||
|
||||
public void testExecuteNoExistingSettings() throws Exception {
|
||||
Map<String, String> includes = randomMap(1, 5);
|
||||
Map<String, String> excludes = randomMap(1, 5);
|
||||
Map<String, String> requires = randomMap(1, 5);
|
||||
Settings.Builder existingSettings = Settings.builder().put("index.version.created", Version.CURRENT.id);
|
||||
Settings.Builder expectedSettings = Settings.builder();
|
||||
includes.forEach((k, v) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v));
|
||||
excludes.forEach((k, v) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v));
|
||||
requires.forEach((k, v) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v));
|
||||
AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
|
||||
assertSettingsUpdate(action, existingSettings, expectedSettings.build());
|
||||
}
|
||||
|
||||
public void testExecuteSettingsUnassignedShards() throws Exception {
|
||||
Map<String, String> includes = randomMap(1, 5);
|
||||
Map<String, String> excludes = randomMap(1, 5);
|
||||
Map<String, String> requires = randomMap(1, 5);
|
||||
Settings.Builder existingSettings = Settings.builder().put("index.version.created", Version.CURRENT.id);
|
||||
Settings.Builder expectedSettings = Settings.builder();
|
||||
includes.forEach((k, v) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v));
|
||||
excludes.forEach((k, v) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v));
|
||||
requires.forEach((k, v) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v));
|
||||
AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
|
||||
assertSettingsUpdate(action, existingSettings, expectedSettings.build());
|
||||
}
|
||||
|
||||
public void testExecuteSomeExistingSettings() throws Exception {
|
||||
Map<String, String> includes = randomMap(1, 5);
|
||||
Map<String, String> excludes = randomMap(1, 5);
|
||||
Map<String, String> requires = randomMap(1, 5);
|
||||
Settings.Builder existingSettings = Settings.builder().put("index.version.created", Version.CURRENT.id);
|
||||
Settings.Builder expectedSettings = Settings.builder();
|
||||
includes.forEach((k, v) -> {
|
||||
if (randomBoolean()) {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
} else {
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
}
|
||||
});
|
||||
excludes.forEach((k, v) -> {
|
||||
if (randomBoolean()) {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
} else {
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
}
|
||||
});
|
||||
requires.forEach((k, v) -> {
|
||||
if (randomBoolean()) {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
} else {
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
}
|
||||
});
|
||||
|
||||
// make sure there is at least one setting that is missing
|
||||
if (expectedSettings.keys().isEmpty()) {
|
||||
String key = randomAlphaOfLengthBetween(1, 20);
|
||||
String value = randomAlphaOfLengthBetween(1, 20);
|
||||
includes.put(key, value);
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + key, value);
|
||||
}
|
||||
AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
|
||||
assertSettingsUpdate(action, existingSettings, expectedSettings.build());
|
||||
}
|
||||
|
||||
public void testExecuteSomeExistingSettingsDifferentValue() throws Exception {
|
||||
Map<String, String> includes = randomMap(1, 5);
|
||||
Map<String, String> excludes = randomMap(1, 5);
|
||||
Map<String, String> requires = randomMap(1, 5);
|
||||
Settings.Builder existingSettings = Settings.builder().put("index.version.created", Version.CURRENT.id);
|
||||
Settings.Builder expectedSettings = Settings.builder();
|
||||
includes.forEach((k, v) -> {
|
||||
if (randomBoolean()) {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
} else {
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v + randomAlphaOfLength(4));
|
||||
}
|
||||
});
|
||||
excludes.forEach((k, v) -> {
|
||||
if (randomBoolean()) {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
} else {
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v + randomAlphaOfLength(4));
|
||||
}
|
||||
});
|
||||
requires.forEach((k, v) -> {
|
||||
if (randomBoolean()) {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
} else {
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v + randomAlphaOfLength(4));
|
||||
}
|
||||
});
|
||||
|
||||
// make sure there is at least one setting that is different
|
||||
if (expectedSettings.keys().isEmpty()) {
|
||||
String key = randomAlphaOfLengthBetween(1, 20);
|
||||
String value = randomAlphaOfLengthBetween(1, 20);
|
||||
includes.put(key, value);
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + key, value);
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + key, value + randomAlphaOfLength(4));
|
||||
}
|
||||
AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
|
||||
assertSettingsUpdate(action, existingSettings, expectedSettings.build());
|
||||
}
|
||||
|
||||
public void testExecuteUpdateSettingsFail() throws Exception {
|
||||
Settings expectedSettings = Settings.builder().put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + "box_type", "foo")
|
||||
.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + "box_type", "bar")
|
||||
.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + "box_type", "baz").build();
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20))
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(randomIntBetween(1, 5))
|
||||
.numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
Index index = indexMetadata.getIndex();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.routingTable(RoutingTable.builder()
|
||||
.add(IndexRoutingTable.builder(index).addShard(
|
||||
TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true, ShardRoutingState.STARTED)))
|
||||
.build())
|
||||
.build();
|
||||
Exception exception = new RuntimeException();
|
||||
|
||||
BiConsumer<Settings, Listener> settingsUpdater = (s, l) -> {
|
||||
assertEquals(expectedSettings, s);
|
||||
l.onFailure(exception);
|
||||
};
|
||||
|
||||
Map<String, String> includes = new HashMap<>();
|
||||
includes.put("box_type", "foo");
|
||||
Map<String, String> excludes = new HashMap<>();
|
||||
excludes.put("box_type", "bar");
|
||||
Map<String, String> requires = new HashMap<>();
|
||||
requires.put("box_type", "baz");
|
||||
|
||||
AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
|
||||
RuntimeException thrownException = expectActionFailure(index, clusterState, null, action, settingsUpdater, RuntimeException.class);
|
||||
assertSame(exception, thrownException);
|
||||
|
||||
}
|
||||
|
||||
public void testExecuteAllocateComplete() throws Exception {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Map<String, String> includes = randomMap(1, 5);
|
||||
Map<String, String> excludes = randomMap(1, 5);
|
||||
Map<String, String> requires = randomMap(1, 5);
|
||||
Settings.Builder existingSettings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT.id)
|
||||
.put(IndexMetaData.SETTING_INDEX_UUID, index.getUUID());
|
||||
Settings.Builder expectedSettings = Settings.builder();
|
||||
Settings.Builder node1Settings = Settings.builder();
|
||||
Settings.Builder node2Settings = Settings.builder();
|
||||
includes.forEach((k, v) -> {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
node1Settings.put(Node.NODE_ATTRIBUTES.getKey() + k, v);
|
||||
});
|
||||
excludes.forEach((k, v) -> {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
});
|
||||
requires.forEach((k, v) -> {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
node1Settings.put(Node.NODE_ATTRIBUTES.getKey() + k, v);
|
||||
});
|
||||
|
||||
IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index)
|
||||
.addShard(TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true, ShardRoutingState.STARTED));
|
||||
|
||||
AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
assertAllocateStatus(index, 1, 0, action, existingSettings, node1Settings, node2Settings, indexRoutingTable,
|
||||
true);
|
||||
}
|
||||
|
||||
public void testExecuteAllocateNotComplete() throws Exception {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Map<String, String> includes = randomMap(1, 5);
|
||||
Map<String, String> excludes = randomMap(1, 5);
|
||||
Map<String, String> requires = randomMap(1, 5);
|
||||
Settings.Builder existingSettings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT.id)
|
||||
.put(IndexMetaData.SETTING_INDEX_UUID, index.getUUID());
|
||||
Settings.Builder expectedSettings = Settings.builder();
|
||||
Settings.Builder node1Settings = Settings.builder();
|
||||
Settings.Builder node2Settings = Settings.builder();
|
||||
includes.forEach((k, v) -> {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
node1Settings.put(Node.NODE_ATTRIBUTES.getKey() + k, v);
|
||||
});
|
||||
excludes.forEach((k, v) -> {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
});
|
||||
requires.forEach((k, v) -> {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
node1Settings.put(Node.NODE_ATTRIBUTES.getKey() + k, v);
|
||||
});
|
||||
|
||||
IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index)
|
||||
.addShard(TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true, ShardRoutingState.STARTED))
|
||||
.addShard(TestShardRouting.newShardRouting(new ShardId(index, 1), "node2", true, ShardRoutingState.STARTED));
|
||||
|
||||
AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
assertAllocateStatus(index, 2, 0, action, existingSettings, node1Settings, node2Settings, indexRoutingTable,
|
||||
false);
|
||||
}
|
||||
|
||||
public void testExecuteAllocateUnassigned() throws Exception {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Map<String, String> includes = randomMap(1, 5);
|
||||
Map<String, String> excludes = randomMap(1, 5);
|
||||
Map<String, String> requires = randomMap(1, 5);
|
||||
Settings.Builder existingSettings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT.id)
|
||||
.put(IndexMetaData.SETTING_INDEX_UUID, index.getUUID());
|
||||
Settings.Builder expectedSettings = Settings.builder();
|
||||
Settings.Builder node1Settings = Settings.builder();
|
||||
Settings.Builder node2Settings = Settings.builder();
|
||||
includes.forEach((k, v) -> {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
node1Settings.put(Node.NODE_ATTRIBUTES.getKey() + k, v);
|
||||
});
|
||||
excludes.forEach((k, v) -> {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
});
|
||||
requires.forEach((k, v) -> {
|
||||
existingSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
node1Settings.put(Node.NODE_ATTRIBUTES.getKey() + k, v);
|
||||
});
|
||||
|
||||
IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index)
|
||||
.addShard(TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true, ShardRoutingState.STARTED))
|
||||
.addShard(TestShardRouting.newShardRouting(new ShardId(index, 1), null, null, true, ShardRoutingState.UNASSIGNED,
|
||||
new UnassignedInfo(randomFrom(Reason.values()), "the shard is intentionally unassigned")));
|
||||
|
||||
AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
assertAllocateStatus(index, 2, 0, action, existingSettings, node1Settings, node2Settings, indexRoutingTable,
|
||||
false);
|
||||
}
|
||||
|
||||
public void testExecuteIndexMissing() throws Exception {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).build();
|
||||
|
||||
BiConsumer<Settings, Listener> settingsUpdater = (s, l) -> {
|
||||
throw new AssertionError("Unexpected settings update");
|
||||
};
|
||||
|
||||
Map<String, String> includes = new HashMap<>();
|
||||
includes.put("box_type", "foo");
|
||||
Map<String, String> excludes = new HashMap<>();
|
||||
excludes.put("box_type", "bar");
|
||||
Map<String, String> requires = new HashMap<>();
|
||||
requires.put("box_type", "baz");
|
||||
|
||||
AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
|
||||
IndexNotFoundException thrownException = expectActionFailure(index, clusterState, null, action, settingsUpdater,
|
||||
IndexNotFoundException.class);
|
||||
assertEquals("Index not found when executing " + AllocateAction.NAME + " lifecycle action.", thrownException.getMessage());
|
||||
assertEquals(index.getName(), thrownException.getIndex().getName());
|
||||
}
|
||||
|
||||
private void assertSettingsUpdate(AllocateAction action, Settings.Builder existingSettings, Settings expectedSettings) {
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20)).settings(existingSettings)
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
Index index = indexMetadata.getIndex();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.routingTable(RoutingTable.builder()
|
||||
.add(IndexRoutingTable.builder(index).addShard(
|
||||
TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true, ShardRoutingState.STARTED)))
|
||||
.build())
|
||||
.build();
|
||||
|
||||
BiConsumer<Settings, Listener> settingsUpdater = (s, l) -> {
|
||||
assertEquals(expectedSettings, s);
|
||||
l.onSuccess(false);
|
||||
};
|
||||
assertActionStatus(index, clusterState, null, action, settingsUpdater, false);
|
||||
}
|
||||
|
||||
private void assertAllocateStatus(Index index, int shards, int replicas, AllocateAction action, Settings.Builder existingSettings,
|
||||
Settings.Builder node1Settings, Settings.Builder node2Settings, IndexRoutingTable.Builder indexRoutingTable,
|
||||
boolean expectComplete) {
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName()).settings(existingSettings).numberOfShards(shards)
|
||||
.numberOfReplicas(replicas).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.nodes(DiscoveryNodes.builder()
|
||||
.add(DiscoveryNode.createLocal(node1Settings.build(), new TransportAddress(TransportAddress.META_ADDRESS, 9200),
|
||||
"node1"))
|
||||
.add(DiscoveryNode.createLocal(node2Settings.build(), new TransportAddress(TransportAddress.META_ADDRESS, 9201),
|
||||
"node2")))
|
||||
.routingTable(RoutingTable.builder().add(indexRoutingTable).build()).build();
|
||||
ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY,
|
||||
Sets.newHashSet(FilterAllocationDecider.CLUSTER_ROUTING_INCLUDE_GROUP_SETTING,
|
||||
FilterAllocationDecider.CLUSTER_ROUTING_EXCLUDE_GROUP_SETTING,
|
||||
FilterAllocationDecider.CLUSTER_ROUTING_REQUIRE_GROUP_SETTING));
|
||||
|
||||
BiConsumer<Settings, Listener> settingsUpdater = (s, l) -> {
|
||||
throw new AssertionError("Unexpected settings update");
|
||||
};
|
||||
|
||||
assertActionStatus(index, clusterState, clusterSettings, action, settingsUpdater, expectComplete);
|
||||
}
|
||||
|
||||
private void assertActionStatus(Index index, ClusterState clusterState, ClusterSettings clusterSettings, AllocateAction action,
|
||||
BiConsumer<Settings, Listener> settingsUpdater, boolean expectComplete) {
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
action.execute(index, settingsUpdater, clusterState, clusterSettings, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(expectComplete, actionCompleted.get());
|
||||
}
|
||||
|
||||
private <E> E expectActionFailure(Index index, ClusterState clusterState, ClusterSettings clusterSettings, AllocateAction action,
|
||||
BiConsumer<Settings, Listener> settingsUpdater, Class<E> expectedExceptionType) {
|
||||
|
||||
SetOnce<E> exceptionThrown = new SetOnce<>();
|
||||
action.execute(index, settingsUpdater, clusterState, clusterSettings, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
assertThat(e, instanceOf(expectedExceptionType));
|
||||
exceptionThrown.set((E) e);
|
||||
}
|
||||
});
|
||||
|
||||
return exceptionThrown.get();
|
||||
}
|
||||
// public void testExecuteNoExistingSettings() throws Exception {
|
||||
// Map<String, String> includes = randomMap(1, 5);
|
||||
// Map<String, String> excludes = randomMap(1, 5);
|
||||
// Map<String, String> requires = randomMap(1, 5);
|
||||
// Settings.Builder existingSettings = Settings.builder().put("index.version.created", Version.CURRENT.id);
|
||||
// Settings.Builder expectedSettings = Settings.builder();
|
||||
// includes.forEach((k, v) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v));
|
||||
// excludes.forEach((k, v) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v));
|
||||
// requires.forEach((k, v) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v));
|
||||
// AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
//
|
||||
// assertSettingsUpdate(action, existingSettings, expectedSettings.build());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteSettingsUnassignedShards() throws Exception {
|
||||
// Map<String, String> includes = randomMap(1, 5);
|
||||
// Map<String, String> excludes = randomMap(1, 5);
|
||||
// Map<String, String> requires = randomMap(1, 5);
|
||||
// Settings.Builder existingSettings = Settings.builder().put("index.version.created", Version.CURRENT.id);
|
||||
// Settings.Builder expectedSettings = Settings.builder();
|
||||
// includes.forEach((k, v) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v));
|
||||
// excludes.forEach((k, v) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v));
|
||||
// requires.forEach((k, v) -> expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v));
|
||||
// AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
//
|
||||
// assertSettingsUpdate(action, existingSettings, expectedSettings.build());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteSomeExistingSettings() throws Exception {
|
||||
// Map<String, String> includes = randomMap(1, 5);
|
||||
// Map<String, String> excludes = randomMap(1, 5);
|
||||
// Map<String, String> requires = randomMap(1, 5);
|
||||
// Settings.Builder existingSettings = Settings.builder().put("index.version.created", Version.CURRENT.id);
|
||||
// Settings.Builder expectedSettings = Settings.builder();
|
||||
// includes.forEach((k, v) -> {
|
||||
// if (randomBoolean()) {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// } else {
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// }
|
||||
// });
|
||||
// excludes.forEach((k, v) -> {
|
||||
// if (randomBoolean()) {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// } else {
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// }
|
||||
// });
|
||||
// requires.forEach((k, v) -> {
|
||||
// if (randomBoolean()) {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
// } else {
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// // make sure there is at least one setting that is missing
|
||||
// if (expectedSettings.keys().isEmpty()) {
|
||||
// String key = randomAlphaOfLengthBetween(1, 20);
|
||||
// String value = randomAlphaOfLengthBetween(1, 20);
|
||||
// includes.put(key, value);
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + key, value);
|
||||
// }
|
||||
// AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
//
|
||||
// assertSettingsUpdate(action, existingSettings, expectedSettings.build());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteSomeExistingSettingsDifferentValue() throws Exception {
|
||||
// Map<String, String> includes = randomMap(1, 5);
|
||||
// Map<String, String> excludes = randomMap(1, 5);
|
||||
// Map<String, String> requires = randomMap(1, 5);
|
||||
// Settings.Builder existingSettings = Settings.builder().put("index.version.created", Version.CURRENT.id);
|
||||
// Settings.Builder expectedSettings = Settings.builder();
|
||||
// includes.forEach((k, v) -> {
|
||||
// if (randomBoolean()) {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// } else {
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v + randomAlphaOfLength(4));
|
||||
// }
|
||||
// });
|
||||
// excludes.forEach((k, v) -> {
|
||||
// if (randomBoolean()) {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// } else {
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v + randomAlphaOfLength(4));
|
||||
// }
|
||||
// });
|
||||
// requires.forEach((k, v) -> {
|
||||
// if (randomBoolean()) {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
// } else {
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v + randomAlphaOfLength(4));
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// // make sure there is at least one setting that is different
|
||||
// if (expectedSettings.keys().isEmpty()) {
|
||||
// String key = randomAlphaOfLengthBetween(1, 20);
|
||||
// String value = randomAlphaOfLengthBetween(1, 20);
|
||||
// includes.put(key, value);
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + key, value);
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + key, value + randomAlphaOfLength(4));
|
||||
// }
|
||||
// AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
//
|
||||
// assertSettingsUpdate(action, existingSettings, expectedSettings.build());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteUpdateSettingsFail() throws Exception {
|
||||
// Settings expectedSettings = Settings.builder().put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + "box_type", "foo")
|
||||
// .put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + "box_type", "bar")
|
||||
// .put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + "box_type", "baz").build();
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20))
|
||||
// .settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(randomIntBetween(1, 5))
|
||||
// .numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// Index index = indexMetadata.getIndex();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .routingTable(RoutingTable.builder()
|
||||
// .add(IndexRoutingTable.builder(index).addShard(
|
||||
// TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true, ShardRoutingState.STARTED)))
|
||||
// .build())
|
||||
// .build();
|
||||
// Exception exception = new RuntimeException();
|
||||
//
|
||||
// BiConsumer<Settings, Listener> settingsUpdater = (s, l) -> {
|
||||
// assertEquals(expectedSettings, s);
|
||||
// l.onFailure(exception);
|
||||
// };
|
||||
//
|
||||
// Map<String, String> includes = new HashMap<>();
|
||||
// includes.put("box_type", "foo");
|
||||
// Map<String, String> excludes = new HashMap<>();
|
||||
// excludes.put("box_type", "bar");
|
||||
// Map<String, String> requires = new HashMap<>();
|
||||
// requires.put("box_type", "baz");
|
||||
//
|
||||
// AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
//
|
||||
// RuntimeException thrownException = expectActionFailure(index, clusterState, null, action, settingsUpdater, RuntimeException.class);
|
||||
// assertSame(exception, thrownException);
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public void testExecuteAllocateComplete() throws Exception {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Map<String, String> includes = randomMap(1, 5);
|
||||
// Map<String, String> excludes = randomMap(1, 5);
|
||||
// Map<String, String> requires = randomMap(1, 5);
|
||||
// Settings.Builder existingSettings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT.id)
|
||||
// .put(IndexMetaData.SETTING_INDEX_UUID, index.getUUID());
|
||||
// Settings.Builder expectedSettings = Settings.builder();
|
||||
// Settings.Builder node1Settings = Settings.builder();
|
||||
// Settings.Builder node2Settings = Settings.builder();
|
||||
// includes.forEach((k, v) -> {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// node1Settings.put(Node.NODE_ATTRIBUTES.getKey() + k, v);
|
||||
// });
|
||||
// excludes.forEach((k, v) -> {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// });
|
||||
// requires.forEach((k, v) -> {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
// node1Settings.put(Node.NODE_ATTRIBUTES.getKey() + k, v);
|
||||
// });
|
||||
//
|
||||
// IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index)
|
||||
// .addShard(TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true, ShardRoutingState.STARTED));
|
||||
//
|
||||
// AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
// assertAllocateStatus(index, 1, 0, action, existingSettings, node1Settings, node2Settings, indexRoutingTable,
|
||||
// true);
|
||||
// }
|
||||
//
|
||||
// public void testExecuteAllocateNotComplete() throws Exception {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Map<String, String> includes = randomMap(1, 5);
|
||||
// Map<String, String> excludes = randomMap(1, 5);
|
||||
// Map<String, String> requires = randomMap(1, 5);
|
||||
// Settings.Builder existingSettings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT.id)
|
||||
// .put(IndexMetaData.SETTING_INDEX_UUID, index.getUUID());
|
||||
// Settings.Builder expectedSettings = Settings.builder();
|
||||
// Settings.Builder node1Settings = Settings.builder();
|
||||
// Settings.Builder node2Settings = Settings.builder();
|
||||
// includes.forEach((k, v) -> {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// node1Settings.put(Node.NODE_ATTRIBUTES.getKey() + k, v);
|
||||
// });
|
||||
// excludes.forEach((k, v) -> {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// });
|
||||
// requires.forEach((k, v) -> {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
// node1Settings.put(Node.NODE_ATTRIBUTES.getKey() + k, v);
|
||||
// });
|
||||
//
|
||||
// IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index)
|
||||
// .addShard(TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true, ShardRoutingState.STARTED))
|
||||
// .addShard(TestShardRouting.newShardRouting(new ShardId(index, 1), "node2", true, ShardRoutingState.STARTED));
|
||||
//
|
||||
// AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
// assertAllocateStatus(index, 2, 0, action, existingSettings, node1Settings, node2Settings, indexRoutingTable,
|
||||
// false);
|
||||
// }
|
||||
//
|
||||
// public void testExecuteAllocateUnassigned() throws Exception {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Map<String, String> includes = randomMap(1, 5);
|
||||
// Map<String, String> excludes = randomMap(1, 5);
|
||||
// Map<String, String> requires = randomMap(1, 5);
|
||||
// Settings.Builder existingSettings = Settings.builder().put(IndexMetaData.SETTING_VERSION_CREATED, Version.CURRENT.id)
|
||||
// .put(IndexMetaData.SETTING_INDEX_UUID, index.getUUID());
|
||||
// Settings.Builder expectedSettings = Settings.builder();
|
||||
// Settings.Builder node1Settings = Settings.builder();
|
||||
// Settings.Builder node2Settings = Settings.builder();
|
||||
// includes.forEach((k, v) -> {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_INCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// node1Settings.put(Node.NODE_ATTRIBUTES.getKey() + k, v);
|
||||
// });
|
||||
// excludes.forEach((k, v) -> {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_EXCLUDE_GROUP_SETTING.getKey() + k, v);
|
||||
// });
|
||||
// requires.forEach((k, v) -> {
|
||||
// existingSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
// expectedSettings.put(IndexMetaData.INDEX_ROUTING_REQUIRE_GROUP_SETTING.getKey() + k, v);
|
||||
// node1Settings.put(Node.NODE_ATTRIBUTES.getKey() + k, v);
|
||||
// });
|
||||
//
|
||||
// IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index)
|
||||
// .addShard(TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true, ShardRoutingState.STARTED))
|
||||
// .addShard(TestShardRouting.newShardRouting(new ShardId(index, 1), null, null, true, ShardRoutingState.UNASSIGNED,
|
||||
// new UnassignedInfo(randomFrom(Reason.values()), "the shard is intentionally unassigned")));
|
||||
//
|
||||
// AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
// assertAllocateStatus(index, 2, 0, action, existingSettings, node1Settings, node2Settings, indexRoutingTable,
|
||||
// false);
|
||||
// }
|
||||
//
|
||||
// public void testExecuteIndexMissing() throws Exception {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).build();
|
||||
//
|
||||
// BiConsumer<Settings, Listener> settingsUpdater = (s, l) -> {
|
||||
// throw new AssertionError("Unexpected settings update");
|
||||
// };
|
||||
//
|
||||
// Map<String, String> includes = new HashMap<>();
|
||||
// includes.put("box_type", "foo");
|
||||
// Map<String, String> excludes = new HashMap<>();
|
||||
// excludes.put("box_type", "bar");
|
||||
// Map<String, String> requires = new HashMap<>();
|
||||
// requires.put("box_type", "baz");
|
||||
//
|
||||
// AllocateAction action = new AllocateAction(includes, excludes, requires);
|
||||
//
|
||||
// IndexNotFoundException thrownException = expectActionFailure(index, clusterState, null, action, settingsUpdater,
|
||||
// IndexNotFoundException.class);
|
||||
// assertEquals("Index not found when executing " + AllocateAction.NAME + " lifecycle action.", thrownException.getMessage());
|
||||
// assertEquals(index.getName(), thrownException.getIndex().getName());
|
||||
// }
|
||||
//
|
||||
// private void assertSettingsUpdate(AllocateAction action, Settings.Builder existingSettings, Settings expectedSettings) {
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20)).settings(existingSettings)
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// Index index = indexMetadata.getIndex();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .routingTable(RoutingTable.builder()
|
||||
// .add(IndexRoutingTable.builder(index).addShard(
|
||||
// TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true, ShardRoutingState.STARTED)))
|
||||
// .build())
|
||||
// .build();
|
||||
//
|
||||
// BiConsumer<Settings, Listener> settingsUpdater = (s, l) -> {
|
||||
// assertEquals(expectedSettings, s);
|
||||
// l.onSuccess(false);
|
||||
// };
|
||||
// assertActionStatus(index, clusterState, null, action, settingsUpdater, false);
|
||||
// }
|
||||
//
|
||||
// private void assertAllocateStatus(Index index, int shards, int replicas, AllocateAction action, Settings.Builder existingSettings,
|
||||
// Settings.Builder node1Settings, Settings.Builder node2Settings, IndexRoutingTable.Builder indexRoutingTable,
|
||||
// boolean expectComplete) {
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName()).settings(existingSettings).numberOfShards(shards)
|
||||
// .numberOfReplicas(replicas).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
//
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .nodes(DiscoveryNodes.builder()
|
||||
// .add(DiscoveryNode.createLocal(node1Settings.build(), new TransportAddress(TransportAddress.META_ADDRESS, 9200),
|
||||
// "node1"))
|
||||
// .add(DiscoveryNode.createLocal(node2Settings.build(), new TransportAddress(TransportAddress.META_ADDRESS, 9201),
|
||||
// "node2")))
|
||||
// .routingTable(RoutingTable.builder().add(indexRoutingTable).build()).build();
|
||||
// ClusterSettings clusterSettings = new ClusterSettings(Settings.EMPTY,
|
||||
// Sets.newHashSet(FilterAllocationDecider.CLUSTER_ROUTING_INCLUDE_GROUP_SETTING,
|
||||
// FilterAllocationDecider.CLUSTER_ROUTING_EXCLUDE_GROUP_SETTING,
|
||||
// FilterAllocationDecider.CLUSTER_ROUTING_REQUIRE_GROUP_SETTING));
|
||||
//
|
||||
// BiConsumer<Settings, Listener> settingsUpdater = (s, l) -> {
|
||||
// throw new AssertionError("Unexpected settings update");
|
||||
// };
|
||||
//
|
||||
// assertActionStatus(index, clusterState, clusterSettings, action, settingsUpdater, expectComplete);
|
||||
// }
|
||||
//
|
||||
// private void assertActionStatus(Index index, ClusterState clusterState, ClusterSettings clusterSettings, AllocateAction action,
|
||||
// BiConsumer<Settings, Listener> settingsUpdater, boolean expectComplete) {
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// action.execute(index, settingsUpdater, clusterState, clusterSettings, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call");
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(expectComplete, actionCompleted.get());
|
||||
// }
|
||||
//
|
||||
// private <E> E expectActionFailure(Index index, ClusterState clusterState, ClusterSettings clusterSettings, AllocateAction action,
|
||||
// BiConsumer<Settings, Listener> settingsUpdater, Class<E> expectedExceptionType) {
|
||||
//
|
||||
// SetOnce<E> exceptionThrown = new SetOnce<>();
|
||||
// action.execute(index, settingsUpdater, clusterState, clusterSettings, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// throw new AssertionError("Unexpected method call");
|
||||
// }
|
||||
//
|
||||
// @SuppressWarnings("unchecked")
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// assertThat(e, instanceOf(expectedExceptionType));
|
||||
// exceptionThrown.set((E) e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// return exceptionThrown.get();
|
||||
// }
|
||||
|
||||
private Map<String, String> randomMap(int minEntries, int maxEntries) {
|
||||
Map<String, String> map = new HashMap<>();
|
||||
|
|
|
@ -16,7 +16,6 @@ import org.elasticsearch.common.io.stream.Writeable.Reader;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.test.AbstractSerializingTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction.Listener;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
@ -40,101 +39,101 @@ public class DeleteActionTests extends AbstractSerializingTestCase<DeleteAction>
|
|||
return DeleteAction::new;
|
||||
}
|
||||
|
||||
public void testExecute() throws Exception {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
DeleteIndexRequest request = (DeleteIndexRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<DeleteIndexResponse> listener = (ActionListener<DeleteIndexResponse>) invocation.getArguments()[1];
|
||||
assertNotNull(request);
|
||||
assertEquals(1, request.indices().length);
|
||||
assertEquals(index.getName(), request.indices()[0]);
|
||||
listener.onResponse(null);
|
||||
return null;
|
||||
}
|
||||
|
||||
}).when(indicesClient).delete(Mockito.any(), Mockito.any());
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
DeleteAction action = new DeleteAction();
|
||||
action.execute(index, client, null, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, actionCompleted.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).delete(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testExecuteFailure() throws Exception {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Exception exception = new RuntimeException();
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
DeleteIndexRequest request = (DeleteIndexRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<DeleteIndexResponse> listener = (ActionListener<DeleteIndexResponse>) invocation.getArguments()[1];
|
||||
assertNotNull(request);
|
||||
assertEquals(1, request.indices().length);
|
||||
assertEquals(index.getName(), request.indices()[0]);
|
||||
listener.onFailure(exception);
|
||||
;
|
||||
return null;
|
||||
}
|
||||
|
||||
}).when(indicesClient).delete(Mockito.any(), Mockito.any());
|
||||
|
||||
SetOnce<Boolean> exceptionThrown = new SetOnce<>();
|
||||
DeleteAction action = new DeleteAction();
|
||||
action.execute(index, client, null, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
assertEquals(exception, e);
|
||||
exceptionThrown.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, exceptionThrown.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).delete(Mockito.any(), Mockito.any());
|
||||
}
|
||||
// public void testExecute() throws Exception {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
// Mockito.doAnswer(new Answer<Void>() {
|
||||
//
|
||||
// @Override
|
||||
// public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
// DeleteIndexRequest request = (DeleteIndexRequest) invocation.getArguments()[0];
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<DeleteIndexResponse> listener = (ActionListener<DeleteIndexResponse>) invocation.getArguments()[1];
|
||||
// assertNotNull(request);
|
||||
// assertEquals(1, request.indices().length);
|
||||
// assertEquals(index.getName(), request.indices()[0]);
|
||||
// listener.onResponse(null);
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// }).when(indicesClient).delete(Mockito.any(), Mockito.any());
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// DeleteAction action = new DeleteAction();
|
||||
// action.execute(index, client, null, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(true, actionCompleted.get());
|
||||
//
|
||||
// Mockito.verify(client, Mockito.only()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.only()).delete(Mockito.any(), Mockito.any());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteFailure() throws Exception {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Exception exception = new RuntimeException();
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
// Mockito.doAnswer(new Answer<Void>() {
|
||||
//
|
||||
// @Override
|
||||
// public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
// DeleteIndexRequest request = (DeleteIndexRequest) invocation.getArguments()[0];
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<DeleteIndexResponse> listener = (ActionListener<DeleteIndexResponse>) invocation.getArguments()[1];
|
||||
// assertNotNull(request);
|
||||
// assertEquals(1, request.indices().length);
|
||||
// assertEquals(index.getName(), request.indices()[0]);
|
||||
// listener.onFailure(exception);
|
||||
// ;
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// }).when(indicesClient).delete(Mockito.any(), Mockito.any());
|
||||
//
|
||||
// SetOnce<Boolean> exceptionThrown = new SetOnce<>();
|
||||
// DeleteAction action = new DeleteAction();
|
||||
// action.execute(index, client, null, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// throw new AssertionError("Unexpected method call");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// assertEquals(exception, e);
|
||||
// exceptionThrown.set(true);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(true, exceptionThrown.get());
|
||||
//
|
||||
// Mockito.verify(client, Mockito.only()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.only()).delete(Mockito.any(), Mockito.any());
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@ import org.elasticsearch.index.Index;
|
|||
import org.elasticsearch.index.engine.Segment;
|
||||
import org.elasticsearch.rest.RestStatus;
|
||||
import org.elasticsearch.test.AbstractSerializingTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction.Listener;
|
||||
import org.mockito.InOrder;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
|
@ -71,7 +70,7 @@ public class ForceMergeActionTests extends AbstractSerializingTestCase<ForceMerg
|
|||
}
|
||||
|
||||
public void testMissingMaxNumSegments() throws IOException {
|
||||
BytesReference emptyObject = JsonXContent.contentBuilder().startObject().endObject().bytes();
|
||||
BytesReference emptyObject = BytesReference.bytes(JsonXContent.contentBuilder().startObject().endObject());
|
||||
XContentParser parser = XContentHelper.createParser(null, DeprecationHandler.THROW_UNSUPPORTED_OPERATION,
|
||||
emptyObject, XContentType.JSON);
|
||||
Exception e = expectThrows(IllegalArgumentException.class, () -> ForceMergeAction.parse(parser));
|
||||
|
@ -83,332 +82,332 @@ public class ForceMergeActionTests extends AbstractSerializingTestCase<ForceMerg
|
|||
assertThat(r.getMessage(), equalTo("[max_num_segments] must be a positive integer"));
|
||||
}
|
||||
|
||||
public void testExecuteSuccessfully() throws Exception {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(settings(Version.CURRENT))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.build();
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
UpdateSettingsResponse updateSettingsResponse = Mockito.mock(UpdateSettingsResponse.class);
|
||||
IndicesSegmentResponse indicesSegmentResponse = Mockito.mock(IndicesSegmentResponse.class);
|
||||
IndexSegments indexSegments = Mockito.mock(IndexSegments.class);
|
||||
IndexShardSegments indexShardSegments = Mockito.mock(IndexShardSegments.class);
|
||||
Map<Integer, IndexShardSegments> indexShards = Collections.singletonMap(0, indexShardSegments);
|
||||
ShardSegments shardSegmentsOne = Mockito.mock(ShardSegments.class);
|
||||
ShardSegments[] shardSegmentsArray = new ShardSegments[] { shardSegmentsOne };
|
||||
Spliterator<IndexShardSegments> iss = indexShards.values().spliterator();
|
||||
List<Segment> segments = Arrays.asList(null, null);
|
||||
ForceMergeResponse forceMergeResponse = Mockito.mock(ForceMergeResponse.class);
|
||||
Mockito.when(forceMergeResponse.getStatus()).thenReturn(RestStatus.OK);
|
||||
Mockito.when(indicesSegmentResponse.getStatus()).thenReturn(RestStatus.OK);
|
||||
Mockito.when(indicesSegmentResponse.getIndices()).thenReturn(Collections.singletonMap(index.getName(), indexSegments));
|
||||
Mockito.when(indexSegments.spliterator()).thenReturn(iss);
|
||||
Mockito.when(indexShardSegments.getShards()).thenReturn(shardSegmentsArray);
|
||||
Mockito.when(shardSegmentsOne.getSegments()).thenReturn(segments);
|
||||
int maxNumSegments = 1;
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<IndicesSegmentResponse> listener = (ActionListener<IndicesSegmentResponse>) invocationOnMock.getArguments()[1];
|
||||
listener.onResponse(indicesSegmentResponse);
|
||||
return null;
|
||||
}).when(indicesClient).segments(any(), any());
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocationOnMock.getArguments()[1];
|
||||
listener.onResponse(updateSettingsResponse);
|
||||
return null;
|
||||
}).when(indicesClient).updateSettings(any(), any());
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
ForceMergeRequest request = (ForceMergeRequest) invocationOnMock.getArguments()[0];
|
||||
assertThat(request.maxNumSegments(), equalTo(maxNumSegments));
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<ForceMergeResponse> listener = (ActionListener<ForceMergeResponse>) invocationOnMock.getArguments()[1];
|
||||
listener.onResponse(forceMergeResponse);
|
||||
return null;
|
||||
}).when(indicesClient).forceMerge(any(), any());
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
ForceMergeAction action = new ForceMergeAction(maxNumSegments);
|
||||
action.execute(index, client, clusterService, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, actionCompleted.get());
|
||||
|
||||
Mockito.verify(client, Mockito.atLeast(1)).admin();
|
||||
Mockito.verify(adminClient, Mockito.atLeast(1)).indices();
|
||||
Mockito.verify(indicesClient, Mockito.atLeast(1)).segments(any(), any());
|
||||
Mockito.verify(indicesClient, Mockito.atLeast(1)).updateSettings(any(), any());
|
||||
Mockito.verify(indicesClient, Mockito.atLeast(1)).forceMerge(any(), any());
|
||||
Mockito.verify(clusterService, Mockito.atLeast(1)).state();
|
||||
}
|
||||
|
||||
public void testExecuteWhenReadOnlyAlready() {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
boolean isReadOnlyAlready = true;
|
||||
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(settings(Version.CURRENT).put(IndexMetaData.SETTING_BLOCKS_WRITE, isReadOnlyAlready))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.build();
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
IndicesSegmentResponse indicesSegmentResponse = Mockito.mock(IndicesSegmentResponse.class);
|
||||
IndexSegments indexSegments = Mockito.mock(IndexSegments.class);
|
||||
IndexShardSegments indexShardSegments = Mockito.mock(IndexShardSegments.class);
|
||||
Map<Integer, IndexShardSegments> indexShards = Collections.singletonMap(0, indexShardSegments);
|
||||
ShardSegments shardSegmentsOne = Mockito.mock(ShardSegments.class);
|
||||
ShardSegments[] shardSegmentsArray = new ShardSegments[] { shardSegmentsOne };
|
||||
Spliterator<IndexShardSegments> iss = indexShards.values().spliterator();
|
||||
List<Segment> segments = Arrays.asList(null, null);
|
||||
|
||||
Mockito.when(indicesSegmentResponse.getStatus()).thenReturn(RestStatus.OK);
|
||||
Mockito.when(indicesSegmentResponse.getIndices()).thenReturn(Collections.singletonMap(index.getName(), indexSegments));
|
||||
Mockito.when(indexSegments.spliterator()).thenReturn(iss);
|
||||
Mockito.when(indexShardSegments.getShards()).thenReturn(shardSegmentsArray);
|
||||
Mockito.when(shardSegmentsOne.getSegments()).thenReturn(segments);
|
||||
int maxNumSegments = Integer.MAX_VALUE;
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<IndicesSegmentResponse> listener = (ActionListener<IndicesSegmentResponse>) invocationOnMock.getArguments()[1];
|
||||
listener.onResponse(indicesSegmentResponse);
|
||||
return null;
|
||||
}).when(indicesClient).segments(any(), any());
|
||||
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
ForceMergeAction action = new ForceMergeAction(maxNumSegments);
|
||||
action.execute(index, client, clusterService, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(null, actionCompleted.get());
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(clusterService, client, adminClient, indicesClient);
|
||||
inOrder.verify(clusterService).state();
|
||||
inOrder.verify(client).admin();
|
||||
inOrder.verify(adminClient).indices();
|
||||
inOrder.verify(indicesClient).segments(any(), any());
|
||||
inOrder.verify(indicesClient).updateSettings(any(), any());
|
||||
Mockito.verify(indicesClient, Mockito.never()).forceMerge(any(), any());
|
||||
}
|
||||
|
||||
public void testExecuteWithNoNeedToForceMerge() {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
boolean isReadOnlyAlready = false;
|
||||
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(settings(Version.CURRENT).put(IndexMetaData.SETTING_BLOCKS_WRITE, isReadOnlyAlready))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.build();
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
IndicesSegmentResponse indicesSegmentResponse = Mockito.mock(IndicesSegmentResponse.class);
|
||||
IndexSegments indexSegments = Mockito.mock(IndexSegments.class);
|
||||
IndexShardSegments indexShardSegments = Mockito.mock(IndexShardSegments.class);
|
||||
Map<Integer, IndexShardSegments> indexShards = Collections.singletonMap(0, indexShardSegments);
|
||||
ShardSegments shardSegmentsOne = Mockito.mock(ShardSegments.class);
|
||||
ShardSegments[] shardSegmentsArray = new ShardSegments[] { shardSegmentsOne };
|
||||
Spliterator<IndexShardSegments> iss = indexShards.values().spliterator();
|
||||
List<Segment> segments = Arrays.asList(null, null);
|
||||
|
||||
Mockito.when(indicesSegmentResponse.getStatus()).thenReturn(RestStatus.OK);
|
||||
Mockito.when(indicesSegmentResponse.getIndices()).thenReturn(Collections.singletonMap(index.getName(), indexSegments));
|
||||
Mockito.when(indexSegments.spliterator()).thenReturn(iss);
|
||||
Mockito.when(indexShardSegments.getShards()).thenReturn(shardSegmentsArray);
|
||||
Mockito.when(shardSegmentsOne.getSegments()).thenReturn(segments);
|
||||
int maxNumSegments = Integer.MAX_VALUE;
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<IndicesSegmentResponse> listener = (ActionListener<IndicesSegmentResponse>) invocationOnMock.getArguments()[1];
|
||||
listener.onResponse(indicesSegmentResponse);
|
||||
return null;
|
||||
}).when(indicesClient).segments(any(), any());
|
||||
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
ForceMergeAction action = new ForceMergeAction(maxNumSegments);
|
||||
action.execute(index, client, clusterService, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, actionCompleted.get());
|
||||
|
||||
InOrder inOrder = Mockito.inOrder(clusterService, client, adminClient, indicesClient);
|
||||
inOrder.verify(clusterService).state();
|
||||
inOrder.verify(client).admin();
|
||||
inOrder.verify(adminClient).indices();
|
||||
inOrder.verify(indicesClient).segments(any(), any());
|
||||
Mockito.verify(indicesClient, Mockito.never()).updateSettings(any(), any());
|
||||
Mockito.verify(indicesClient, Mockito.never()).forceMerge(any(), any());
|
||||
}
|
||||
|
||||
public void testCheckSegmentsNeedsMerging() {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
IndicesSegmentResponse indicesSegmentResponse = Mockito.mock(IndicesSegmentResponse.class);
|
||||
IndexSegments indexSegments = Mockito.mock(IndexSegments.class);
|
||||
IndexShardSegments indexShardSegments = Mockito.mock(IndexShardSegments.class);
|
||||
Map<Integer, IndexShardSegments> indexShards = Collections.singletonMap(0, indexShardSegments);
|
||||
ShardSegments shardSegmentsOne = Mockito.mock(ShardSegments.class);
|
||||
ShardSegments[] shardSegmentsArray = new ShardSegments[] { shardSegmentsOne };
|
||||
Spliterator<IndexShardSegments> iss = indexShards.values().spliterator();
|
||||
List<Segment> segments = Arrays.asList(null, null);
|
||||
Mockito.when(indicesSegmentResponse.getStatus()).thenReturn(RestStatus.OK);
|
||||
Mockito.when(indicesSegmentResponse.getIndices()).thenReturn(Collections.singletonMap(index.getName(), indexSegments));
|
||||
Mockito.when(indexSegments.spliterator()).thenReturn(iss);
|
||||
Mockito.when(indexShardSegments.getShards()).thenReturn(shardSegmentsArray);
|
||||
Mockito.when(shardSegmentsOne.getSegments()).thenReturn(segments);
|
||||
int maxNumSegments = 1;
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<IndicesSegmentResponse> listener = (ActionListener<IndicesSegmentResponse>) invocationOnMock.getArguments()[1];
|
||||
listener.onResponse(indicesSegmentResponse);
|
||||
return null;
|
||||
}).when(indicesClient).segments(any(), any());
|
||||
|
||||
SetOnce<Boolean> nextActionCalled = new SetOnce<>();
|
||||
ForceMergeAction action = new ForceMergeAction(maxNumSegments);
|
||||
action.checkSegments(index, client, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
throw new AssertionError("Unexpected method call to onSuccess");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
}, r -> nextActionCalled.set(true), r2 -> {throw new AssertionError("unexpected call to action");});
|
||||
|
||||
assertEquals(true, nextActionCalled.get());
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).segments(any(), any());
|
||||
}
|
||||
|
||||
public void testCheckSegmentsNoNeedToMerge() {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
IndicesSegmentResponse indicesSegmentResponse = Mockito.mock(IndicesSegmentResponse.class);
|
||||
IndexSegments indexSegments = Mockito.mock(IndexSegments.class);
|
||||
IndexShardSegments indexShardSegments = Mockito.mock(IndexShardSegments.class);
|
||||
Map<Integer, IndexShardSegments> indexShards = Collections.singletonMap(0, indexShardSegments);
|
||||
ShardSegments shardSegmentsOne = Mockito.mock(ShardSegments.class);
|
||||
ShardSegments[] shardSegmentsArray = new ShardSegments[] { shardSegmentsOne };
|
||||
Spliterator<IndexShardSegments> iss = indexShards.values().spliterator();
|
||||
List<Segment> segments = Arrays.asList(null, null);
|
||||
Mockito.when(indicesSegmentResponse.getStatus()).thenReturn(RestStatus.OK);
|
||||
Mockito.when(indicesSegmentResponse.getIndices()).thenReturn(Collections.singletonMap(index.getName(), indexSegments));
|
||||
Mockito.when(indexSegments.spliterator()).thenReturn(iss);
|
||||
Mockito.when(indexShardSegments.getShards()).thenReturn(shardSegmentsArray);
|
||||
Mockito.when(shardSegmentsOne.getSegments()).thenReturn(segments);
|
||||
int maxNumSegments = randomIntBetween(2, Integer.MAX_VALUE);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<IndicesSegmentResponse> listener = (ActionListener<IndicesSegmentResponse>) invocationOnMock.getArguments()[1];
|
||||
listener.onResponse(indicesSegmentResponse);
|
||||
return null;
|
||||
}).when(indicesClient).segments(any(), any());
|
||||
|
||||
SetOnce<Boolean> skipActionCalled = new SetOnce<>();
|
||||
ForceMergeAction action = new ForceMergeAction(maxNumSegments);
|
||||
action.checkSegments(index, client, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
throw new AssertionError("Unexpected method call to onSuccess");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
}, r -> { throw new AssertionError("next action should not be called"); },
|
||||
r2 -> skipActionCalled.set(true));
|
||||
|
||||
assertTrue(skipActionCalled.get());
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).segments(any(), any());
|
||||
}
|
||||
// public void testExecuteSuccessfully() throws Exception {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
//
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(settings(Version.CURRENT))
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .build();
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// UpdateSettingsResponse updateSettingsResponse = Mockito.mock(UpdateSettingsResponse.class);
|
||||
// IndicesSegmentResponse indicesSegmentResponse = Mockito.mock(IndicesSegmentResponse.class);
|
||||
// IndexSegments indexSegments = Mockito.mock(IndexSegments.class);
|
||||
// IndexShardSegments indexShardSegments = Mockito.mock(IndexShardSegments.class);
|
||||
// Map<Integer, IndexShardSegments> indexShards = Collections.singletonMap(0, indexShardSegments);
|
||||
// ShardSegments shardSegmentsOne = Mockito.mock(ShardSegments.class);
|
||||
// ShardSegments[] shardSegmentsArray = new ShardSegments[] { shardSegmentsOne };
|
||||
// Spliterator<IndexShardSegments> iss = indexShards.values().spliterator();
|
||||
// List<Segment> segments = Arrays.asList(null, null);
|
||||
// ForceMergeResponse forceMergeResponse = Mockito.mock(ForceMergeResponse.class);
|
||||
// Mockito.when(forceMergeResponse.getStatus()).thenReturn(RestStatus.OK);
|
||||
// Mockito.when(indicesSegmentResponse.getStatus()).thenReturn(RestStatus.OK);
|
||||
// Mockito.when(indicesSegmentResponse.getIndices()).thenReturn(Collections.singletonMap(index.getName(), indexSegments));
|
||||
// Mockito.when(indexSegments.spliterator()).thenReturn(iss);
|
||||
// Mockito.when(indexShardSegments.getShards()).thenReturn(shardSegmentsArray);
|
||||
// Mockito.when(shardSegmentsOne.getSegments()).thenReturn(segments);
|
||||
// int maxNumSegments = 1;
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<IndicesSegmentResponse> listener = (ActionListener<IndicesSegmentResponse>) invocationOnMock.getArguments()[1];
|
||||
// listener.onResponse(indicesSegmentResponse);
|
||||
// return null;
|
||||
// }).when(indicesClient).segments(any(), any());
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocationOnMock.getArguments()[1];
|
||||
// listener.onResponse(updateSettingsResponse);
|
||||
// return null;
|
||||
// }).when(indicesClient).updateSettings(any(), any());
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// ForceMergeRequest request = (ForceMergeRequest) invocationOnMock.getArguments()[0];
|
||||
// assertThat(request.maxNumSegments(), equalTo(maxNumSegments));
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<ForceMergeResponse> listener = (ActionListener<ForceMergeResponse>) invocationOnMock.getArguments()[1];
|
||||
// listener.onResponse(forceMergeResponse);
|
||||
// return null;
|
||||
// }).when(indicesClient).forceMerge(any(), any());
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// ForceMergeAction action = new ForceMergeAction(maxNumSegments);
|
||||
// action.execute(index, client, clusterService, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(true, actionCompleted.get());
|
||||
//
|
||||
// Mockito.verify(client, Mockito.atLeast(1)).admin();
|
||||
// Mockito.verify(adminClient, Mockito.atLeast(1)).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.atLeast(1)).segments(any(), any());
|
||||
// Mockito.verify(indicesClient, Mockito.atLeast(1)).updateSettings(any(), any());
|
||||
// Mockito.verify(indicesClient, Mockito.atLeast(1)).forceMerge(any(), any());
|
||||
// Mockito.verify(clusterService, Mockito.atLeast(1)).state();
|
||||
// }
|
||||
//
|
||||
// public void testExecuteWhenReadOnlyAlready() {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// boolean isReadOnlyAlready = true;
|
||||
//
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(settings(Version.CURRENT).put(IndexMetaData.SETTING_BLOCKS_WRITE, isReadOnlyAlready))
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .build();
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// IndicesSegmentResponse indicesSegmentResponse = Mockito.mock(IndicesSegmentResponse.class);
|
||||
// IndexSegments indexSegments = Mockito.mock(IndexSegments.class);
|
||||
// IndexShardSegments indexShardSegments = Mockito.mock(IndexShardSegments.class);
|
||||
// Map<Integer, IndexShardSegments> indexShards = Collections.singletonMap(0, indexShardSegments);
|
||||
// ShardSegments shardSegmentsOne = Mockito.mock(ShardSegments.class);
|
||||
// ShardSegments[] shardSegmentsArray = new ShardSegments[] { shardSegmentsOne };
|
||||
// Spliterator<IndexShardSegments> iss = indexShards.values().spliterator();
|
||||
// List<Segment> segments = Arrays.asList(null, null);
|
||||
//
|
||||
// Mockito.when(indicesSegmentResponse.getStatus()).thenReturn(RestStatus.OK);
|
||||
// Mockito.when(indicesSegmentResponse.getIndices()).thenReturn(Collections.singletonMap(index.getName(), indexSegments));
|
||||
// Mockito.when(indexSegments.spliterator()).thenReturn(iss);
|
||||
// Mockito.when(indexShardSegments.getShards()).thenReturn(shardSegmentsArray);
|
||||
// Mockito.when(shardSegmentsOne.getSegments()).thenReturn(segments);
|
||||
// int maxNumSegments = Integer.MAX_VALUE;
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
//
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<IndicesSegmentResponse> listener = (ActionListener<IndicesSegmentResponse>) invocationOnMock.getArguments()[1];
|
||||
// listener.onResponse(indicesSegmentResponse);
|
||||
// return null;
|
||||
// }).when(indicesClient).segments(any(), any());
|
||||
//
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// ForceMergeAction action = new ForceMergeAction(maxNumSegments);
|
||||
// action.execute(index, client, clusterService, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(null, actionCompleted.get());
|
||||
//
|
||||
// InOrder inOrder = Mockito.inOrder(clusterService, client, adminClient, indicesClient);
|
||||
// inOrder.verify(clusterService).state();
|
||||
// inOrder.verify(client).admin();
|
||||
// inOrder.verify(adminClient).indices();
|
||||
// inOrder.verify(indicesClient).segments(any(), any());
|
||||
// inOrder.verify(indicesClient).updateSettings(any(), any());
|
||||
// Mockito.verify(indicesClient, Mockito.never()).forceMerge(any(), any());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteWithNoNeedToForceMerge() {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// boolean isReadOnlyAlready = false;
|
||||
//
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(settings(Version.CURRENT).put(IndexMetaData.SETTING_BLOCKS_WRITE, isReadOnlyAlready))
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .build();
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// IndicesSegmentResponse indicesSegmentResponse = Mockito.mock(IndicesSegmentResponse.class);
|
||||
// IndexSegments indexSegments = Mockito.mock(IndexSegments.class);
|
||||
// IndexShardSegments indexShardSegments = Mockito.mock(IndexShardSegments.class);
|
||||
// Map<Integer, IndexShardSegments> indexShards = Collections.singletonMap(0, indexShardSegments);
|
||||
// ShardSegments shardSegmentsOne = Mockito.mock(ShardSegments.class);
|
||||
// ShardSegments[] shardSegmentsArray = new ShardSegments[] { shardSegmentsOne };
|
||||
// Spliterator<IndexShardSegments> iss = indexShards.values().spliterator();
|
||||
// List<Segment> segments = Arrays.asList(null, null);
|
||||
//
|
||||
// Mockito.when(indicesSegmentResponse.getStatus()).thenReturn(RestStatus.OK);
|
||||
// Mockito.when(indicesSegmentResponse.getIndices()).thenReturn(Collections.singletonMap(index.getName(), indexSegments));
|
||||
// Mockito.when(indexSegments.spliterator()).thenReturn(iss);
|
||||
// Mockito.when(indexShardSegments.getShards()).thenReturn(shardSegmentsArray);
|
||||
// Mockito.when(shardSegmentsOne.getSegments()).thenReturn(segments);
|
||||
// int maxNumSegments = Integer.MAX_VALUE;
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
//
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<IndicesSegmentResponse> listener = (ActionListener<IndicesSegmentResponse>) invocationOnMock.getArguments()[1];
|
||||
// listener.onResponse(indicesSegmentResponse);
|
||||
// return null;
|
||||
// }).when(indicesClient).segments(any(), any());
|
||||
//
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// ForceMergeAction action = new ForceMergeAction(maxNumSegments);
|
||||
// action.execute(index, client, clusterService, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(true, actionCompleted.get());
|
||||
//
|
||||
// InOrder inOrder = Mockito.inOrder(clusterService, client, adminClient, indicesClient);
|
||||
// inOrder.verify(clusterService).state();
|
||||
// inOrder.verify(client).admin();
|
||||
// inOrder.verify(adminClient).indices();
|
||||
// inOrder.verify(indicesClient).segments(any(), any());
|
||||
// Mockito.verify(indicesClient, Mockito.never()).updateSettings(any(), any());
|
||||
// Mockito.verify(indicesClient, Mockito.never()).forceMerge(any(), any());
|
||||
// }
|
||||
//
|
||||
// public void testCheckSegmentsNeedsMerging() {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// IndicesSegmentResponse indicesSegmentResponse = Mockito.mock(IndicesSegmentResponse.class);
|
||||
// IndexSegments indexSegments = Mockito.mock(IndexSegments.class);
|
||||
// IndexShardSegments indexShardSegments = Mockito.mock(IndexShardSegments.class);
|
||||
// Map<Integer, IndexShardSegments> indexShards = Collections.singletonMap(0, indexShardSegments);
|
||||
// ShardSegments shardSegmentsOne = Mockito.mock(ShardSegments.class);
|
||||
// ShardSegments[] shardSegmentsArray = new ShardSegments[] { shardSegmentsOne };
|
||||
// Spliterator<IndexShardSegments> iss = indexShards.values().spliterator();
|
||||
// List<Segment> segments = Arrays.asList(null, null);
|
||||
// Mockito.when(indicesSegmentResponse.getStatus()).thenReturn(RestStatus.OK);
|
||||
// Mockito.when(indicesSegmentResponse.getIndices()).thenReturn(Collections.singletonMap(index.getName(), indexSegments));
|
||||
// Mockito.when(indexSegments.spliterator()).thenReturn(iss);
|
||||
// Mockito.when(indexShardSegments.getShards()).thenReturn(shardSegmentsArray);
|
||||
// Mockito.when(shardSegmentsOne.getSegments()).thenReturn(segments);
|
||||
// int maxNumSegments = 1;
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<IndicesSegmentResponse> listener = (ActionListener<IndicesSegmentResponse>) invocationOnMock.getArguments()[1];
|
||||
// listener.onResponse(indicesSegmentResponse);
|
||||
// return null;
|
||||
// }).when(indicesClient).segments(any(), any());
|
||||
//
|
||||
// SetOnce<Boolean> nextActionCalled = new SetOnce<>();
|
||||
// ForceMergeAction action = new ForceMergeAction(maxNumSegments);
|
||||
// action.checkSegments(index, client, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// throw new AssertionError("Unexpected method call to onSuccess");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// }, r -> nextActionCalled.set(true), r2 -> {throw new AssertionError("unexpected call to action");});
|
||||
//
|
||||
// assertEquals(true, nextActionCalled.get());
|
||||
// Mockito.verify(client, Mockito.only()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.only()).segments(any(), any());
|
||||
// }
|
||||
//
|
||||
// public void testCheckSegmentsNoNeedToMerge() {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// IndicesSegmentResponse indicesSegmentResponse = Mockito.mock(IndicesSegmentResponse.class);
|
||||
// IndexSegments indexSegments = Mockito.mock(IndexSegments.class);
|
||||
// IndexShardSegments indexShardSegments = Mockito.mock(IndexShardSegments.class);
|
||||
// Map<Integer, IndexShardSegments> indexShards = Collections.singletonMap(0, indexShardSegments);
|
||||
// ShardSegments shardSegmentsOne = Mockito.mock(ShardSegments.class);
|
||||
// ShardSegments[] shardSegmentsArray = new ShardSegments[] { shardSegmentsOne };
|
||||
// Spliterator<IndexShardSegments> iss = indexShards.values().spliterator();
|
||||
// List<Segment> segments = Arrays.asList(null, null);
|
||||
// Mockito.when(indicesSegmentResponse.getStatus()).thenReturn(RestStatus.OK);
|
||||
// Mockito.when(indicesSegmentResponse.getIndices()).thenReturn(Collections.singletonMap(index.getName(), indexSegments));
|
||||
// Mockito.when(indexSegments.spliterator()).thenReturn(iss);
|
||||
// Mockito.when(indexShardSegments.getShards()).thenReturn(shardSegmentsArray);
|
||||
// Mockito.when(shardSegmentsOne.getSegments()).thenReturn(segments);
|
||||
// int maxNumSegments = randomIntBetween(2, Integer.MAX_VALUE);
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<IndicesSegmentResponse> listener = (ActionListener<IndicesSegmentResponse>) invocationOnMock.getArguments()[1];
|
||||
// listener.onResponse(indicesSegmentResponse);
|
||||
// return null;
|
||||
// }).when(indicesClient).segments(any(), any());
|
||||
//
|
||||
// SetOnce<Boolean> skipActionCalled = new SetOnce<>();
|
||||
// ForceMergeAction action = new ForceMergeAction(maxNumSegments);
|
||||
// action.checkSegments(index, client, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// throw new AssertionError("Unexpected method call to onSuccess");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// }, r -> { throw new AssertionError("next action should not be called"); },
|
||||
// r2 -> skipActionCalled.set(true));
|
||||
//
|
||||
// assertTrue(skipActionCalled.get());
|
||||
// Mockito.verify(client, Mockito.only()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.only()).segments(any(), any());
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -16,10 +16,14 @@ import org.elasticsearch.common.xcontent.ConstructingObjectParser;
|
|||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
public class MockAction implements LifecycleAction {
|
||||
public static final ParseField COMPLETED_FIELD = new ParseField("completed");
|
||||
|
@ -29,9 +33,10 @@ public class MockAction implements LifecycleAction {
|
|||
private final AtomicLong executedCount;
|
||||
private Exception exceptionToThrow = null;
|
||||
private boolean completeOnExecute = false;
|
||||
private final List<Step> steps;
|
||||
|
||||
private static final ConstructingObjectParser<MockAction, Void> PARSER = new ConstructingObjectParser<>(NAME,
|
||||
a -> new MockAction((Boolean) a[0], (Long) a[1]));
|
||||
a -> new MockAction(null, (Boolean) a[0], (Long) a[1]));
|
||||
static {
|
||||
PARSER.declareBoolean(ConstructingObjectParser.optionalConstructorArg(), COMPLETED_FIELD);
|
||||
PARSER.declareLong(ConstructingObjectParser.constructorArg(), EXECUTED_COUNT_FIELD);
|
||||
|
@ -41,11 +46,12 @@ public class MockAction implements LifecycleAction {
|
|||
return PARSER.apply(parser, null);
|
||||
}
|
||||
|
||||
public MockAction() {
|
||||
this(null, 0);
|
||||
public MockAction(List<Step> steps) {
|
||||
this(steps, null, 0);
|
||||
}
|
||||
|
||||
MockAction(Boolean completed, long executedCount) {
|
||||
MockAction(List<Step> steps, Boolean completed, long executedCount) {
|
||||
this.steps = steps;
|
||||
if (completed != null) {
|
||||
this.completed.set(completed);
|
||||
}
|
||||
|
@ -53,6 +59,12 @@ public class MockAction implements LifecycleAction {
|
|||
}
|
||||
|
||||
public MockAction(StreamInput in) throws IOException {
|
||||
int numSteps = in.readVInt();
|
||||
this.steps = new ArrayList<>();
|
||||
for (int i = 0; i < numSteps; i++) {
|
||||
// TODO(talevy): make Steps implement NamedWriteable
|
||||
steps.add(null);
|
||||
}
|
||||
Boolean executed = in.readOptionalBoolean();
|
||||
if (executed != null) {
|
||||
this.completed.set(executed);
|
||||
|
@ -76,6 +88,11 @@ public class MockAction implements LifecycleAction {
|
|||
return NAME;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Step> toSteps(String phase, Index index, Client client, ThreadPool threadPool, LongSupplier nowSupplier) {
|
||||
return steps;
|
||||
}
|
||||
|
||||
public void setCompleteOnExecute(boolean completeOnExecute) {
|
||||
this.completeOnExecute = completeOnExecute;
|
||||
}
|
||||
|
@ -102,19 +119,6 @@ public class MockAction implements LifecycleAction {
|
|||
out.writeLong(executedCount.get());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(Index index, Client client, ClusterService clusterService, Listener listener) {
|
||||
executedCount.incrementAndGet();
|
||||
if (exceptionToThrow == null) {
|
||||
if (completeOnExecute) {
|
||||
completed.set(true);
|
||||
}
|
||||
listener.onSuccess(completeOnExecute);
|
||||
} else {
|
||||
listener.onFailure(exceptionToThrow);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(completed.get(), executedCount.get());
|
||||
|
@ -137,5 +141,4 @@ public class MockAction implements LifecycleAction {
|
|||
public String toString() {
|
||||
return Strings.toString(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -16,7 +16,7 @@ public class MockActionTests extends AbstractSerializingTestCase<MockAction> {
|
|||
|
||||
@Override
|
||||
protected MockAction createTestInstance() {
|
||||
return new MockAction(randomBoolean() ? null : randomBoolean(), randomLong());
|
||||
return new MockAction(null, randomBoolean() ? null : randomBoolean(), randomLong());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -43,145 +43,145 @@ public class MockActionTests extends AbstractSerializingTestCase<MockAction> {
|
|||
default:
|
||||
throw new AssertionError("Illegal randomisation branch");
|
||||
}
|
||||
return new MockAction(completed, executedCount);
|
||||
return new MockAction(null, completed, executedCount);
|
||||
}
|
||||
|
||||
public void testExecuteNotComplete() {
|
||||
|
||||
MockAction action = new MockAction();
|
||||
action.setCompleteOnExecute(false);
|
||||
|
||||
assertFalse(action.wasCompleted());
|
||||
assertEquals(0L, action.getExecutedCount());
|
||||
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
|
||||
action.execute(null, null, null, new LifecycleAction.Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertFalse(action.wasCompleted());
|
||||
assertEquals(1L, action.getExecutedCount());
|
||||
assertEquals(true, listenerCalled.get());
|
||||
}
|
||||
|
||||
public void testExecuteComplete() {
|
||||
|
||||
MockAction action = new MockAction();
|
||||
action.setCompleteOnExecute(true);
|
||||
|
||||
assertFalse(action.wasCompleted());
|
||||
assertEquals(0L, action.getExecutedCount());
|
||||
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
|
||||
action.execute(null, null, null, new LifecycleAction.Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(action.wasCompleted());
|
||||
assertEquals(1L, action.getExecutedCount());
|
||||
assertEquals(true, listenerCalled.get());
|
||||
}
|
||||
|
||||
public void testResetComplete() {
|
||||
|
||||
MockAction action = new MockAction();
|
||||
action.setCompleteOnExecute(true);
|
||||
|
||||
assertFalse(action.wasCompleted());
|
||||
assertEquals(0L, action.getExecutedCount());
|
||||
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
|
||||
action.execute(null, null, null, new LifecycleAction.Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(action.wasCompleted());
|
||||
assertEquals(1L, action.getExecutedCount());
|
||||
assertEquals(true, listenerCalled.get());
|
||||
|
||||
action.resetCompleted();
|
||||
|
||||
assertFalse(action.wasCompleted());
|
||||
|
||||
SetOnce<Boolean> listenerCalled2 = new SetOnce<>();
|
||||
|
||||
action.execute(null, null, null, new LifecycleAction.Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
listenerCalled2.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(action.wasCompleted());
|
||||
assertEquals(2L, action.getExecutedCount());
|
||||
assertEquals(true, listenerCalled2.get());
|
||||
}
|
||||
|
||||
public void testExecuteFailure() {
|
||||
Exception exception = new RuntimeException();
|
||||
|
||||
MockAction action = new MockAction();
|
||||
action.setCompleteOnExecute(randomBoolean());
|
||||
action.setExceptionToThrow(exception);
|
||||
|
||||
assertFalse(action.wasCompleted());
|
||||
assertEquals(0L, action.getExecutedCount());
|
||||
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
|
||||
action.execute(null, null, null, new LifecycleAction.Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
assertSame(exception, e);
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
assertFalse(action.wasCompleted());
|
||||
assertEquals(1L, action.getExecutedCount());
|
||||
assertEquals(true, listenerCalled.get());
|
||||
}
|
||||
// public void testExecuteNotComplete() {
|
||||
//
|
||||
// MockAction action = new MockAction();
|
||||
// action.setCompleteOnExecute(false);
|
||||
//
|
||||
// assertFalse(action.wasCompleted());
|
||||
// assertEquals(0L, action.getExecutedCount());
|
||||
//
|
||||
// SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
//
|
||||
// action.execute(null, null, null, new LifecycleAction.Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// listenerCalled.set(true);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertFalse(action.wasCompleted());
|
||||
// assertEquals(1L, action.getExecutedCount());
|
||||
// assertEquals(true, listenerCalled.get());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteComplete() {
|
||||
//
|
||||
// MockAction action = new MockAction();
|
||||
// action.setCompleteOnExecute(true);
|
||||
//
|
||||
// assertFalse(action.wasCompleted());
|
||||
// assertEquals(0L, action.getExecutedCount());
|
||||
//
|
||||
// SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
//
|
||||
// action.execute(null, null, null, new LifecycleAction.Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// listenerCalled.set(true);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertTrue(action.wasCompleted());
|
||||
// assertEquals(1L, action.getExecutedCount());
|
||||
// assertEquals(true, listenerCalled.get());
|
||||
// }
|
||||
//
|
||||
// public void testResetComplete() {
|
||||
//
|
||||
// MockAction action = new MockAction();
|
||||
// action.setCompleteOnExecute(true);
|
||||
//
|
||||
// assertFalse(action.wasCompleted());
|
||||
// assertEquals(0L, action.getExecutedCount());
|
||||
//
|
||||
// SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
//
|
||||
// action.execute(null, null, null, new LifecycleAction.Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// listenerCalled.set(true);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertTrue(action.wasCompleted());
|
||||
// assertEquals(1L, action.getExecutedCount());
|
||||
// assertEquals(true, listenerCalled.get());
|
||||
//
|
||||
// action.resetCompleted();
|
||||
//
|
||||
// assertFalse(action.wasCompleted());
|
||||
//
|
||||
// SetOnce<Boolean> listenerCalled2 = new SetOnce<>();
|
||||
//
|
||||
// action.execute(null, null, null, new LifecycleAction.Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// listenerCalled2.set(true);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertTrue(action.wasCompleted());
|
||||
// assertEquals(2L, action.getExecutedCount());
|
||||
// assertEquals(true, listenerCalled2.get());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteFailure() {
|
||||
// Exception exception = new RuntimeException();
|
||||
//
|
||||
// MockAction action = new MockAction();
|
||||
// action.setCompleteOnExecute(randomBoolean());
|
||||
// action.setExceptionToThrow(exception);
|
||||
//
|
||||
// assertFalse(action.wasCompleted());
|
||||
// assertEquals(0L, action.getExecutedCount());
|
||||
//
|
||||
// SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
//
|
||||
// action.execute(null, null, null, new LifecycleAction.Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// throw new AssertionError("Unexpected method call");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// assertSame(exception, e);
|
||||
// listenerCalled.set(true);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertFalse(action.wasCompleted());
|
||||
// assertEquals(1L, action.getExecutedCount());
|
||||
// assertEquals(true, listenerCalled.get());
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* 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.indexlifecycle;
|
||||
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
public abstract class MockIndexLifecycleContext implements IndexLifecycleContext {
|
||||
|
||||
private final String targetName;
|
||||
private String phase;
|
||||
private String action;
|
||||
private Exception exceptionToThrow;
|
||||
private int numberOfReplicas;
|
||||
private LongSupplier nowSupplier;
|
||||
private long phaseTime;
|
||||
private long actionTime;
|
||||
|
||||
public MockIndexLifecycleContext(String targetName, String initialPhase, String initialAction, int numberOfReplicas,
|
||||
LongSupplier nowSupplier) {
|
||||
this.targetName = targetName;
|
||||
this.phase = initialPhase;
|
||||
this.action = initialAction;
|
||||
this.numberOfReplicas = numberOfReplicas;
|
||||
this.nowSupplier = nowSupplier;
|
||||
this.phaseTime = -1L;
|
||||
this.actionTime = -1L;
|
||||
}
|
||||
|
||||
public void failOnSetters(Exception exceptionToThrow) {
|
||||
this.exceptionToThrow = exceptionToThrow;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPhase(String phase, Listener listener) {
|
||||
if (exceptionToThrow != null) {
|
||||
listener.onFailure(exceptionToThrow);
|
||||
return;
|
||||
}
|
||||
this.phase = phase;
|
||||
this.phaseTime = nowSupplier.getAsLong();
|
||||
this.action = "";
|
||||
this.actionTime = -1L;
|
||||
listener.onSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAction(String action, Listener listener) {
|
||||
if (exceptionToThrow != null) {
|
||||
listener.onFailure(exceptionToThrow);
|
||||
return;
|
||||
}
|
||||
this.action = action;
|
||||
this.actionTime = nowSupplier.getAsLong();
|
||||
listener.onSuccess();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getActionTime() {
|
||||
return actionTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPhase() {
|
||||
return phase;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPhaseTime() {
|
||||
return phaseTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLifecycleTarget() {
|
||||
return targetName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfReplicas() {
|
||||
return numberOfReplicas;
|
||||
}
|
||||
|
||||
@Override
|
||||
public abstract boolean canExecute(Phase phase);
|
||||
|
||||
@Override
|
||||
public void executeAction(LifecycleAction action, LifecycleAction.Listener listener) {
|
||||
action.execute(null, null, null, listener);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,256 +0,0 @@
|
|||
/*
|
||||
* 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.indexlifecycle;
|
||||
|
||||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleContext.Listener;
|
||||
|
||||
public class MockIndexLifecycleContextTests extends ESTestCase {
|
||||
|
||||
public void testSetPhase() {
|
||||
String targetName = randomAlphaOfLengthBetween(1, 20);
|
||||
String newPhase = randomAlphaOfLengthBetween(1, 20);
|
||||
long now = randomNonNegativeLong();
|
||||
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(targetName,
|
||||
randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20), randomIntBetween(0, 10), () -> now) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
|
||||
// Use setOnce so it throws an error if we call the listener multiple
|
||||
// times
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
context.setPhase(newPhase, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected Error", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, listenerCalled.get());
|
||||
assertEquals(newPhase, context.getPhase());
|
||||
assertEquals("", context.getAction());
|
||||
assertEquals(now, context.getPhaseTime());
|
||||
assertEquals(-1L, context.getActionTime());
|
||||
assertEquals(targetName, context.getLifecycleTarget());
|
||||
}
|
||||
|
||||
public void testGetPhase() {
|
||||
String phase = randomAlphaOfLengthBetween(1, 20);
|
||||
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(randomAlphaOfLengthBetween(1, 20), phase,
|
||||
randomAlphaOfLengthBetween(1, 20), randomIntBetween(0, 10), () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
|
||||
assertEquals(phase, context.getPhase());
|
||||
}
|
||||
|
||||
public void testGetReplicas() {
|
||||
int replicas = randomIntBetween(1, 10);
|
||||
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(randomAlphaOfLengthBetween(1, 20),
|
||||
randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20), replicas, () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
|
||||
assertEquals(replicas, context.getNumberOfReplicas());
|
||||
}
|
||||
|
||||
public void testSetAction() {
|
||||
String targetName = randomAlphaOfLengthBetween(1, 20);
|
||||
String phase = randomAlphaOfLengthBetween(1, 20);
|
||||
String newAction = randomAlphaOfLengthBetween(1, 20);
|
||||
long now = randomNonNegativeLong();
|
||||
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(targetName, phase,
|
||||
randomAlphaOfLengthBetween(1, 20), randomIntBetween(0, 10), () -> now) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
|
||||
// Use setOnce so it throws an error if we call the listener multiple
|
||||
// times
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
context.setAction(newAction, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected Error", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, listenerCalled.get());
|
||||
assertEquals(newAction, context.getAction());
|
||||
assertEquals(phase, context.getPhase());
|
||||
assertEquals(-1L, context.getPhaseTime()); // no setPhase was called to set this yet
|
||||
assertEquals(now, context.getActionTime());
|
||||
assertEquals(targetName, context.getLifecycleTarget());
|
||||
}
|
||||
|
||||
public void testGetAction() {
|
||||
String action = randomAlphaOfLengthBetween(1, 20);
|
||||
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(randomAlphaOfLengthBetween(1, 20),
|
||||
randomAlphaOfLengthBetween(1, 20), action, randomIntBetween(0, 10), () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
|
||||
assertEquals(action, context.getAction());
|
||||
}
|
||||
|
||||
public void testGetLifecycleTarget() {
|
||||
String target = randomAlphaOfLengthBetween(1, 20);
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(target, randomAlphaOfLengthBetween(1, 20),
|
||||
randomAlphaOfLengthBetween(1, 20), randomIntBetween(0, 10), () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
|
||||
assertEquals(target, context.getLifecycleTarget());
|
||||
}
|
||||
|
||||
public void testExecuteAction() {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(randomAlphaOfLengthBetween(1, 20),
|
||||
randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20), randomIntBetween(0, 10), () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
|
||||
MockAction action = new MockAction();
|
||||
action.setCompleteOnExecute(true);
|
||||
|
||||
assertFalse(action.wasCompleted());
|
||||
assertEquals(0L, action.getExecutedCount());
|
||||
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
|
||||
context.executeAction(action, new LifecycleAction.Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(action.wasCompleted());
|
||||
assertEquals(1L, action.getExecutedCount());
|
||||
assertEquals(true, listenerCalled.get());
|
||||
}
|
||||
|
||||
public void testFailOnPhaseSetter() {
|
||||
|
||||
String phase = randomAlphaOfLengthBetween(1, 20);
|
||||
String action = randomAlphaOfLengthBetween(1, 20);
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(randomAlphaOfLengthBetween(1, 20),
|
||||
phase, action, randomIntBetween(0, 10), () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
RuntimeException exception = new RuntimeException();
|
||||
context.failOnSetters(exception);
|
||||
|
||||
SetOnce<Exception> listenerCalled = new SetOnce<>();
|
||||
|
||||
context.setPhase(randomAlphaOfLengthBetween(1, 20), new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
listenerCalled.set(e);
|
||||
}
|
||||
});
|
||||
|
||||
assertSame(exception, listenerCalled.get());
|
||||
assertEquals(phase, context.getPhase());
|
||||
assertEquals(action, context.getAction());
|
||||
}
|
||||
|
||||
public void testFailOnActionSetter() {
|
||||
|
||||
String phase = randomAlphaOfLengthBetween(1, 20);
|
||||
String action = randomAlphaOfLengthBetween(1, 20);
|
||||
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(randomAlphaOfLengthBetween(1, 20),
|
||||
phase, action, randomIntBetween(0, 10), () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
RuntimeException exception = new RuntimeException();
|
||||
context.failOnSetters(exception);
|
||||
|
||||
SetOnce<Exception> listenerCalled = new SetOnce<>();
|
||||
|
||||
context.setAction(randomAlphaOfLengthBetween(1, 20), new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
listenerCalled.set(e);
|
||||
}
|
||||
});
|
||||
|
||||
assertSame(exception, listenerCalled.get());
|
||||
assertEquals(phase, context.getPhase());
|
||||
assertEquals(action, context.getAction());
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -29,7 +29,7 @@ import org.elasticsearch.common.xcontent.XContentParser;
|
|||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.test.AbstractSerializingTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction.Listener;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
@ -64,310 +64,310 @@ public class ReplicasActionTests extends AbstractSerializingTestCase<ReplicasAct
|
|||
assertEquals("[" + ReplicasAction.NUMBER_OF_REPLICAS_FIELD.getPreferredName() + "] must be >= 0", exception.getMessage());
|
||||
}
|
||||
|
||||
public void testExecuteDifferentReplicaCount() {
|
||||
int existingNumReplicas = randomIntBetween(0, 10);
|
||||
int newNumReplicas = randomValueOtherThan(existingNumReplicas, () -> randomIntBetween(0, 10));
|
||||
|
||||
ReplicasAction action = new ReplicasAction(newNumReplicas);
|
||||
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20))
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(randomIntBetween(1, 5))
|
||||
.numberOfReplicas(existingNumReplicas).build();
|
||||
Index index = indexMetadata.getIndex();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.build();
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
UpdateSettingsRequest request = (UpdateSettingsRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocation.getArguments()[1];
|
||||
Settings expectedSettings = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, newNumReplicas).build();
|
||||
UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, index.getName());
|
||||
listener.onResponse(UpdateSettingsTestHelper.createMockResponse(true));
|
||||
return null;
|
||||
}
|
||||
|
||||
}).when(indicesClient).updateSettings(Mockito.any(), Mockito.any());
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
action.execute(index, client, clusterService, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(false, actionCompleted.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).updateSettings(Mockito.any(), Mockito.any());
|
||||
Mockito.verify(clusterService, Mockito.only()).state();
|
||||
}
|
||||
|
||||
public void testExecuteUpdateReplicaCountFailure() {
|
||||
int existingNumReplicas = randomIntBetween(0, 10);
|
||||
int newNumReplicas = randomValueOtherThan(existingNumReplicas, () -> randomIntBetween(0, 10));
|
||||
|
||||
ReplicasAction action = new ReplicasAction(newNumReplicas);
|
||||
Exception exception = new RuntimeException();
|
||||
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20))
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(randomIntBetween(1, 5))
|
||||
.numberOfReplicas(existingNumReplicas).build();
|
||||
Index index = indexMetadata.getIndex();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.build();
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
UpdateSettingsRequest request = (UpdateSettingsRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocation.getArguments()[1];
|
||||
Settings expectedSettings = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, newNumReplicas).build();
|
||||
UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, index.getName());
|
||||
listener.onFailure(exception);
|
||||
return null;
|
||||
}
|
||||
|
||||
}).when(indicesClient).updateSettings(Mockito.any(), Mockito.any());
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
|
||||
SetOnce<Boolean> exceptionThrown = new SetOnce<>();
|
||||
action.execute(index, client, clusterService, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
exceptionThrown.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, exceptionThrown.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).updateSettings(Mockito.any(), Mockito.any());
|
||||
Mockito.verify(clusterService, Mockito.only()).state();
|
||||
}
|
||||
|
||||
public void testExecuteAllocationNotComplete() {
|
||||
|
||||
ReplicasAction action = new ReplicasAction(randomIntBetween(1, 10));
|
||||
|
||||
int numberOfShards = randomIntBetween(1, 5);
|
||||
int numberOfReplicas = action.getNumberOfReplicas();
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20))
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(numberOfShards)
|
||||
.numberOfReplicas(numberOfReplicas).build();
|
||||
Index index = indexMetadata.getIndex();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index);
|
||||
for (int shard = 0; shard < numberOfShards; shard++) {
|
||||
for (int replica = 0; replica < numberOfReplicas + 1; replica++) {
|
||||
ShardRoutingState state;
|
||||
if (replica == 0) {
|
||||
state = ShardRoutingState.STARTED;
|
||||
} else if ((replica == numberOfReplicas) || randomBoolean()) {
|
||||
state = randomFrom(ShardRoutingState.UNASSIGNED, ShardRoutingState.INITIALIZING);
|
||||
} else {
|
||||
state = ShardRoutingState.STARTED;
|
||||
}
|
||||
String nodeId = "node" + replica;
|
||||
if (ShardRoutingState.UNASSIGNED.equals(state)) {
|
||||
nodeId = null;
|
||||
}
|
||||
indexRoutingTable.addShard(TestShardRouting.newShardRouting(new ShardId(index, shard), nodeId, replica == 0, state));
|
||||
}
|
||||
}
|
||||
ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.routingTable(RoutingTable.builder().add(indexRoutingTable).build())
|
||||
.build();
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
action.execute(index, client, clusterService, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(false, actionCompleted.get());
|
||||
|
||||
Mockito.verify(clusterService, Mockito.times(2)).state();
|
||||
Mockito.verify(client, Mockito.never()).admin();
|
||||
Mockito.verify(adminClient, Mockito.never()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.never()).updateSettings(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testExecuteAllocationUnassignedPrimaries() {
|
||||
|
||||
ReplicasAction action = createTestInstance();
|
||||
|
||||
int numberOfShards = randomIntBetween(1, 5);
|
||||
int numberOfReplicas = action.getNumberOfReplicas();
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20))
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(numberOfShards)
|
||||
.numberOfReplicas(numberOfReplicas).build();
|
||||
Index index = indexMetadata.getIndex();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index);
|
||||
for (int shard = 0; shard < numberOfShards; shard++) {
|
||||
boolean unassignedPrimary = shard == 0 || randomBoolean();
|
||||
for (int replica = 0; replica < numberOfReplicas + 1; replica++) {
|
||||
ShardRoutingState state;
|
||||
if (unassignedPrimary) {
|
||||
state = ShardRoutingState.UNASSIGNED;
|
||||
} else if (replica == 0) {
|
||||
state = ShardRoutingState.STARTED;
|
||||
} else if ((replica == numberOfReplicas) || randomBoolean()) {
|
||||
state = randomFrom(ShardRoutingState.UNASSIGNED, ShardRoutingState.INITIALIZING);
|
||||
} else {
|
||||
state = ShardRoutingState.STARTED;
|
||||
}
|
||||
String nodeId = "node" + replica;
|
||||
if (ShardRoutingState.UNASSIGNED.equals(state)) {
|
||||
nodeId = null;
|
||||
}
|
||||
indexRoutingTable.addShard(TestShardRouting.newShardRouting(new ShardId(index, shard), nodeId, replica == 0, state));
|
||||
}
|
||||
}
|
||||
ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.routingTable(RoutingTable.builder().add(indexRoutingTable).build()).build();
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
action.execute(index, client, clusterService, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(false, actionCompleted.get());
|
||||
|
||||
Mockito.verify(clusterService, Mockito.times(2)).state();
|
||||
Mockito.verify(client, Mockito.never()).admin();
|
||||
Mockito.verify(adminClient, Mockito.never()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.never()).updateSettings(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testExecuteAllocationComplete() {
|
||||
|
||||
ReplicasAction action = createTestInstance();
|
||||
|
||||
int numberOfShards = randomIntBetween(1, 5);
|
||||
int numberOfReplicas = action.getNumberOfReplicas();
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20))
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(numberOfShards)
|
||||
.numberOfReplicas(numberOfReplicas).build();
|
||||
Index index = indexMetadata.getIndex();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index);
|
||||
for (int shard = 0; shard < numberOfShards; shard++) {
|
||||
for (int replica = 0; replica < numberOfReplicas + 1; replica++) {
|
||||
ShardRoutingState state = ShardRoutingState.STARTED;
|
||||
String nodeId = "node" + replica;
|
||||
indexRoutingTable.addShard(TestShardRouting.newShardRouting(new ShardId(index, shard), nodeId, replica == 0, state));
|
||||
}
|
||||
}
|
||||
ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.routingTable(RoutingTable.builder().add(indexRoutingTable).build()).build();
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
action.execute(index, client, clusterService, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, actionCompleted.get());
|
||||
|
||||
Mockito.verify(clusterService, Mockito.times(2)).state();
|
||||
Mockito.verify(client, Mockito.never()).admin();
|
||||
Mockito.verify(adminClient, Mockito.never()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.never()).updateSettings(Mockito.any(), Mockito.any());
|
||||
}
|
||||
// public void testExecuteDifferentReplicaCount() {
|
||||
// int existingNumReplicas = randomIntBetween(0, 10);
|
||||
// int newNumReplicas = randomValueOtherThan(existingNumReplicas, () -> randomIntBetween(0, 10));
|
||||
//
|
||||
// ReplicasAction action = new ReplicasAction(newNumReplicas);
|
||||
//
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20))
|
||||
// .settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(randomIntBetween(1, 5))
|
||||
// .numberOfReplicas(existingNumReplicas).build();
|
||||
// Index index = indexMetadata.getIndex();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .build();
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
// Mockito.doAnswer(new Answer<Void>() {
|
||||
//
|
||||
// @Override
|
||||
// public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
// UpdateSettingsRequest request = (UpdateSettingsRequest) invocation.getArguments()[0];
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocation.getArguments()[1];
|
||||
// Settings expectedSettings = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, newNumReplicas).build();
|
||||
// UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, index.getName());
|
||||
// listener.onResponse(UpdateSettingsTestHelper.createMockResponse(true));
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// }).when(indicesClient).updateSettings(Mockito.any(), Mockito.any());
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// action.execute(index, client, clusterService, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(false, actionCompleted.get());
|
||||
//
|
||||
// Mockito.verify(client, Mockito.only()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.only()).updateSettings(Mockito.any(), Mockito.any());
|
||||
// Mockito.verify(clusterService, Mockito.only()).state();
|
||||
// }
|
||||
//
|
||||
// public void testExecuteUpdateReplicaCountFailure() {
|
||||
// int existingNumReplicas = randomIntBetween(0, 10);
|
||||
// int newNumReplicas = randomValueOtherThan(existingNumReplicas, () -> randomIntBetween(0, 10));
|
||||
//
|
||||
// ReplicasAction action = new ReplicasAction(newNumReplicas);
|
||||
// Exception exception = new RuntimeException();
|
||||
//
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20))
|
||||
// .settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(randomIntBetween(1, 5))
|
||||
// .numberOfReplicas(existingNumReplicas).build();
|
||||
// Index index = indexMetadata.getIndex();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .build();
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
// Mockito.doAnswer(new Answer<Void>() {
|
||||
//
|
||||
// @Override
|
||||
// public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
// UpdateSettingsRequest request = (UpdateSettingsRequest) invocation.getArguments()[0];
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocation.getArguments()[1];
|
||||
// Settings expectedSettings = Settings.builder().put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, newNumReplicas).build();
|
||||
// UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, index.getName());
|
||||
// listener.onFailure(exception);
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// }).when(indicesClient).updateSettings(Mockito.any(), Mockito.any());
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
//
|
||||
// SetOnce<Boolean> exceptionThrown = new SetOnce<>();
|
||||
// action.execute(index, client, clusterService, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// throw new AssertionError("Unexpected method call");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// exceptionThrown.set(true);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(true, exceptionThrown.get());
|
||||
//
|
||||
// Mockito.verify(client, Mockito.only()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.only()).updateSettings(Mockito.any(), Mockito.any());
|
||||
// Mockito.verify(clusterService, Mockito.only()).state();
|
||||
// }
|
||||
//
|
||||
// public void testExecuteAllocationNotComplete() {
|
||||
//
|
||||
// ReplicasAction action = new ReplicasAction(randomIntBetween(1, 10));
|
||||
//
|
||||
// int numberOfShards = randomIntBetween(1, 5);
|
||||
// int numberOfReplicas = action.getNumberOfReplicas();
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20))
|
||||
// .settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(numberOfShards)
|
||||
// .numberOfReplicas(numberOfReplicas).build();
|
||||
// Index index = indexMetadata.getIndex();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index);
|
||||
// for (int shard = 0; shard < numberOfShards; shard++) {
|
||||
// for (int replica = 0; replica < numberOfReplicas + 1; replica++) {
|
||||
// ShardRoutingState state;
|
||||
// if (replica == 0) {
|
||||
// state = ShardRoutingState.STARTED;
|
||||
// } else if ((replica == numberOfReplicas) || randomBoolean()) {
|
||||
// state = randomFrom(ShardRoutingState.UNASSIGNED, ShardRoutingState.INITIALIZING);
|
||||
// } else {
|
||||
// state = ShardRoutingState.STARTED;
|
||||
// }
|
||||
// String nodeId = "node" + replica;
|
||||
// if (ShardRoutingState.UNASSIGNED.equals(state)) {
|
||||
// nodeId = null;
|
||||
// }
|
||||
// indexRoutingTable.addShard(TestShardRouting.newShardRouting(new ShardId(index, shard), nodeId, replica == 0, state));
|
||||
// }
|
||||
// }
|
||||
// ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .routingTable(RoutingTable.builder().add(indexRoutingTable).build())
|
||||
// .build();
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// action.execute(index, client, clusterService, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(false, actionCompleted.get());
|
||||
//
|
||||
// Mockito.verify(clusterService, Mockito.times(2)).state();
|
||||
// Mockito.verify(client, Mockito.never()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.never()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.never()).updateSettings(Mockito.any(), Mockito.any());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteAllocationUnassignedPrimaries() {
|
||||
//
|
||||
// ReplicasAction action = createTestInstance();
|
||||
//
|
||||
// int numberOfShards = randomIntBetween(1, 5);
|
||||
// int numberOfReplicas = action.getNumberOfReplicas();
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20))
|
||||
// .settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(numberOfShards)
|
||||
// .numberOfReplicas(numberOfReplicas).build();
|
||||
// Index index = indexMetadata.getIndex();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index);
|
||||
// for (int shard = 0; shard < numberOfShards; shard++) {
|
||||
// boolean unassignedPrimary = shard == 0 || randomBoolean();
|
||||
// for (int replica = 0; replica < numberOfReplicas + 1; replica++) {
|
||||
// ShardRoutingState state;
|
||||
// if (unassignedPrimary) {
|
||||
// state = ShardRoutingState.UNASSIGNED;
|
||||
// } else if (replica == 0) {
|
||||
// state = ShardRoutingState.STARTED;
|
||||
// } else if ((replica == numberOfReplicas) || randomBoolean()) {
|
||||
// state = randomFrom(ShardRoutingState.UNASSIGNED, ShardRoutingState.INITIALIZING);
|
||||
// } else {
|
||||
// state = ShardRoutingState.STARTED;
|
||||
// }
|
||||
// String nodeId = "node" + replica;
|
||||
// if (ShardRoutingState.UNASSIGNED.equals(state)) {
|
||||
// nodeId = null;
|
||||
// }
|
||||
// indexRoutingTable.addShard(TestShardRouting.newShardRouting(new ShardId(index, shard), nodeId, replica == 0, state));
|
||||
// }
|
||||
// }
|
||||
// ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .routingTable(RoutingTable.builder().add(indexRoutingTable).build()).build();
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// action.execute(index, client, clusterService, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(false, actionCompleted.get());
|
||||
//
|
||||
// Mockito.verify(clusterService, Mockito.times(2)).state();
|
||||
// Mockito.verify(client, Mockito.never()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.never()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.never()).updateSettings(Mockito.any(), Mockito.any());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteAllocationComplete() {
|
||||
//
|
||||
// ReplicasAction action = createTestInstance();
|
||||
//
|
||||
// int numberOfShards = randomIntBetween(1, 5);
|
||||
// int numberOfReplicas = action.getNumberOfReplicas();
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(randomAlphaOfLengthBetween(1, 20))
|
||||
// .settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(numberOfShards)
|
||||
// .numberOfReplicas(numberOfReplicas).build();
|
||||
// Index index = indexMetadata.getIndex();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// IndexRoutingTable.Builder indexRoutingTable = IndexRoutingTable.builder(index);
|
||||
// for (int shard = 0; shard < numberOfShards; shard++) {
|
||||
// for (int replica = 0; replica < numberOfReplicas + 1; replica++) {
|
||||
// ShardRoutingState state = ShardRoutingState.STARTED;
|
||||
// String nodeId = "node" + replica;
|
||||
// indexRoutingTable.addShard(TestShardRouting.newShardRouting(new ShardId(index, shard), nodeId, replica == 0, state));
|
||||
// }
|
||||
// }
|
||||
// ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .routingTable(RoutingTable.builder().add(indexRoutingTable).build()).build();
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// action.execute(index, client, clusterService, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(true, actionCompleted.get());
|
||||
//
|
||||
// Mockito.verify(clusterService, Mockito.times(2)).state();
|
||||
// Mockito.verify(client, Mockito.never()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.never()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.never()).updateSettings(Mockito.any(), Mockito.any());
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -32,8 +32,8 @@ import org.elasticsearch.common.unit.TimeValue;
|
|||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.test.AbstractSerializingTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction.Listener;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.RolloverAction;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
@ -105,247 +105,247 @@ public class RolloverActionTests extends AbstractSerializingTestCase<RolloverAct
|
|||
assertEquals(RolloverAction.ALIAS_FIELD.getPreferredName() + " must be not be null", exception.getMessage());
|
||||
}
|
||||
|
||||
public void testExecute() throws Exception {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
|
||||
RolloverAction action = createTestInstance();
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT.id))
|
||||
.putAlias(AliasMetaData.builder(action.getAlias()))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.build();
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
RolloverRequest request = (RolloverRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<RolloverResponse> listener = (ActionListener<RolloverResponse>) invocation.getArguments()[1];
|
||||
Set<Condition<?>> expectedConditions = new HashSet<>();
|
||||
if (action.getMaxAge() != null) {
|
||||
expectedConditions.add(new MaxAgeCondition(action.getMaxAge()));
|
||||
}
|
||||
if (action.getMaxSize() != null) {
|
||||
expectedConditions.add(new MaxSizeCondition(action.getMaxSize()));
|
||||
}
|
||||
if (action.getMaxDocs() != null) {
|
||||
expectedConditions.add(new MaxDocsCondition(action.getMaxDocs()));
|
||||
}
|
||||
RolloverIndexTestHelper.assertRolloverIndexRequest(request, action.getAlias(), expectedConditions);
|
||||
listener.onResponse(RolloverIndexTestHelper.createMockResponse(request, true));
|
||||
return null;
|
||||
}
|
||||
|
||||
}).when(indicesClient).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
action.execute(index, client, clusterService, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, actionCompleted.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
Mockito.verify(clusterService, Mockito.only()).state();
|
||||
}
|
||||
|
||||
public void testExecuteNotComplete() throws Exception {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
|
||||
RolloverAction action = createTestInstance();
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT.id))
|
||||
.putAlias(AliasMetaData.builder(action.getAlias())).numberOfShards(randomIntBetween(1, 5))
|
||||
.numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.build();
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
RolloverRequest request = (RolloverRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<RolloverResponse> listener = (ActionListener<RolloverResponse>) invocation.getArguments()[1];
|
||||
Set<Condition<?>> expectedConditions = new HashSet<>();
|
||||
if (action.getMaxAge() != null) {
|
||||
expectedConditions.add(new MaxAgeCondition(action.getMaxAge()));
|
||||
}
|
||||
if (action.getMaxSize() != null) {
|
||||
expectedConditions.add(new MaxSizeCondition(action.getMaxSize()));
|
||||
}
|
||||
if (action.getMaxDocs() != null) {
|
||||
expectedConditions.add(new MaxDocsCondition(action.getMaxDocs()));
|
||||
}
|
||||
RolloverIndexTestHelper.assertRolloverIndexRequest(request, action.getAlias(), expectedConditions);
|
||||
listener.onResponse(RolloverIndexTestHelper.createMockResponse(request, false));
|
||||
return null;
|
||||
}
|
||||
|
||||
}).when(indicesClient).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
action.execute(index, client, clusterService, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(false, actionCompleted.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
Mockito.verify(clusterService, Mockito.only()).state();
|
||||
}
|
||||
|
||||
public void testExecuteAlreadyCompleted() throws Exception {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
|
||||
RolloverAction action = createTestInstance();
|
||||
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(randomIntBetween(1, 5))
|
||||
.numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.build();
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
action.execute(index, client, clusterService, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, actionCompleted.get());
|
||||
|
||||
Mockito.verify(clusterService, Mockito.only()).state();
|
||||
Mockito.verifyZeroInteractions(client, adminClient, indicesClient);
|
||||
}
|
||||
|
||||
public void testExecuteFailure() throws Exception {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Exception exception = new RuntimeException();
|
||||
|
||||
RolloverAction action = createTestInstance();
|
||||
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(Settings.builder().put("index.version.created", Version.CURRENT.id))
|
||||
.putAlias(AliasMetaData.builder(action.getAlias())).numberOfShards(randomIntBetween(1, 5))
|
||||
.numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.build();
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
RolloverRequest request = (RolloverRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<RolloverResponse> listener = (ActionListener<RolloverResponse>) invocation.getArguments()[1];
|
||||
Set<Condition<?>> expectedConditions = new HashSet<>();
|
||||
if (action.getMaxAge() != null) {
|
||||
expectedConditions.add(new MaxAgeCondition(action.getMaxAge()));
|
||||
}
|
||||
if (action.getMaxSize() != null) {
|
||||
expectedConditions.add(new MaxSizeCondition(action.getMaxSize()));
|
||||
}
|
||||
if (action.getMaxDocs() != null) {
|
||||
expectedConditions.add(new MaxDocsCondition(action.getMaxDocs()));
|
||||
}
|
||||
RolloverIndexTestHelper.assertRolloverIndexRequest(request, action.getAlias(), expectedConditions);
|
||||
listener.onFailure(exception);
|
||||
return null;
|
||||
}
|
||||
|
||||
}).when(indicesClient).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
|
||||
SetOnce<Boolean> exceptionThrown = new SetOnce<>();
|
||||
action.execute(index, client, clusterService, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
assertEquals(exception, e);
|
||||
exceptionThrown.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, exceptionThrown.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
}
|
||||
// public void testExecute() throws Exception {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
//
|
||||
// RolloverAction action = createTestInstance();
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(Settings.builder().put("index.version.created", Version.CURRENT.id))
|
||||
// .putAlias(AliasMetaData.builder(action.getAlias()))
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .build();
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
// Mockito.doAnswer(new Answer<Void>() {
|
||||
//
|
||||
// @Override
|
||||
// public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
// RolloverRequest request = (RolloverRequest) invocation.getArguments()[0];
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<RolloverResponse> listener = (ActionListener<RolloverResponse>) invocation.getArguments()[1];
|
||||
// Set<Condition<?>> expectedConditions = new HashSet<>();
|
||||
// if (action.getMaxAge() != null) {
|
||||
// expectedConditions.add(new MaxAgeCondition(action.getMaxAge()));
|
||||
// }
|
||||
// if (action.getMaxSize() != null) {
|
||||
// expectedConditions.add(new MaxSizeCondition(action.getMaxSize()));
|
||||
// }
|
||||
// if (action.getMaxDocs() != null) {
|
||||
// expectedConditions.add(new MaxDocsCondition(action.getMaxDocs()));
|
||||
// }
|
||||
// RolloverIndexTestHelper.assertRolloverIndexRequest(request, action.getAlias(), expectedConditions);
|
||||
// listener.onResponse(RolloverIndexTestHelper.createMockResponse(request, true));
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// }).when(indicesClient).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// action.execute(index, client, clusterService, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(true, actionCompleted.get());
|
||||
//
|
||||
// Mockito.verify(client, Mockito.only()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.only()).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
// Mockito.verify(clusterService, Mockito.only()).state();
|
||||
// }
|
||||
//
|
||||
// public void testExecuteNotComplete() throws Exception {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
//
|
||||
// RolloverAction action = createTestInstance();
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(Settings.builder().put("index.version.created", Version.CURRENT.id))
|
||||
// .putAlias(AliasMetaData.builder(action.getAlias())).numberOfShards(randomIntBetween(1, 5))
|
||||
// .numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .build();
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
// Mockito.doAnswer(new Answer<Void>() {
|
||||
//
|
||||
// @Override
|
||||
// public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
// RolloverRequest request = (RolloverRequest) invocation.getArguments()[0];
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<RolloverResponse> listener = (ActionListener<RolloverResponse>) invocation.getArguments()[1];
|
||||
// Set<Condition<?>> expectedConditions = new HashSet<>();
|
||||
// if (action.getMaxAge() != null) {
|
||||
// expectedConditions.add(new MaxAgeCondition(action.getMaxAge()));
|
||||
// }
|
||||
// if (action.getMaxSize() != null) {
|
||||
// expectedConditions.add(new MaxSizeCondition(action.getMaxSize()));
|
||||
// }
|
||||
// if (action.getMaxDocs() != null) {
|
||||
// expectedConditions.add(new MaxDocsCondition(action.getMaxDocs()));
|
||||
// }
|
||||
// RolloverIndexTestHelper.assertRolloverIndexRequest(request, action.getAlias(), expectedConditions);
|
||||
// listener.onResponse(RolloverIndexTestHelper.createMockResponse(request, false));
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// }).when(indicesClient).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// action.execute(index, client, clusterService, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(false, actionCompleted.get());
|
||||
//
|
||||
// Mockito.verify(client, Mockito.only()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.only()).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
// Mockito.verify(clusterService, Mockito.only()).state();
|
||||
// }
|
||||
//
|
||||
// public void testExecuteAlreadyCompleted() throws Exception {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
//
|
||||
// RolloverAction action = createTestInstance();
|
||||
//
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(Settings.builder().put("index.version.created", Version.CURRENT.id)).numberOfShards(randomIntBetween(1, 5))
|
||||
// .numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .build();
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
//
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// action.execute(index, client, clusterService, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(true, actionCompleted.get());
|
||||
//
|
||||
// Mockito.verify(clusterService, Mockito.only()).state();
|
||||
// Mockito.verifyZeroInteractions(client, adminClient, indicesClient);
|
||||
// }
|
||||
//
|
||||
// public void testExecuteFailure() throws Exception {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Exception exception = new RuntimeException();
|
||||
//
|
||||
// RolloverAction action = createTestInstance();
|
||||
//
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(Settings.builder().put("index.version.created", Version.CURRENT.id))
|
||||
// .putAlias(AliasMetaData.builder(action.getAlias())).numberOfShards(randomIntBetween(1, 5))
|
||||
// .numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterstate = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .build();
|
||||
//
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
//
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
// Mockito.doAnswer(new Answer<Void>() {
|
||||
//
|
||||
// @Override
|
||||
// public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
// RolloverRequest request = (RolloverRequest) invocation.getArguments()[0];
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<RolloverResponse> listener = (ActionListener<RolloverResponse>) invocation.getArguments()[1];
|
||||
// Set<Condition<?>> expectedConditions = new HashSet<>();
|
||||
// if (action.getMaxAge() != null) {
|
||||
// expectedConditions.add(new MaxAgeCondition(action.getMaxAge()));
|
||||
// }
|
||||
// if (action.getMaxSize() != null) {
|
||||
// expectedConditions.add(new MaxSizeCondition(action.getMaxSize()));
|
||||
// }
|
||||
// if (action.getMaxDocs() != null) {
|
||||
// expectedConditions.add(new MaxDocsCondition(action.getMaxDocs()));
|
||||
// }
|
||||
// RolloverIndexTestHelper.assertRolloverIndexRequest(request, action.getAlias(), expectedConditions);
|
||||
// listener.onFailure(exception);
|
||||
// return null;
|
||||
// }
|
||||
//
|
||||
// }).when(indicesClient).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterstate);
|
||||
//
|
||||
// SetOnce<Boolean> exceptionThrown = new SetOnce<>();
|
||||
// action.execute(index, client, clusterService, new Listener() {
|
||||
//
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// throw new AssertionError("Unexpected method call");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// assertEquals(exception, e);
|
||||
// exceptionThrown.set(true);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertEquals(true, exceptionThrown.get());
|
||||
//
|
||||
// Mockito.verify(client, Mockito.only()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.only()).rolloverIndex(Mockito.any(), Mockito.any());
|
||||
// }
|
||||
|
||||
}
|
||||
|
|
|
@ -41,9 +41,7 @@ import org.elasticsearch.common.xcontent.XContentParser;
|
|||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.index.shard.ShardId;
|
||||
import org.elasticsearch.test.AbstractSerializingTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.ShrinkAction;
|
||||
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -79,480 +77,480 @@ public class ShrinkActionTests extends AbstractSerializingTestCase<ShrinkAction>
|
|||
assertThat(e.getMessage(), equalTo("[number_of_shards] must be greater than 0"));
|
||||
}
|
||||
|
||||
public void testExecuteSuccessfullyCompleted() {
|
||||
String originalIndexName = randomAlphaOfLengthBetween(1, 20);
|
||||
Index index = new Index("shrunk-" + originalIndexName, randomAlphaOfLengthBetween(1, 20));
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
IndexMetaData originalIndexMetaData = IndexMetaData.builder(originalIndexName)
|
||||
.settings(settings(Version.CURRENT)).numberOfReplicas(0).numberOfShards(1).build();
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(settings(Version.CURRENT).put(IndexMetaData.INDEX_SHRINK_SOURCE_NAME_KEY, originalIndexName))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata).fPut(originalIndexName, originalIndexMetaData);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.build();
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
IndicesAliasesRequest request = (IndicesAliasesRequest) invocationOnMock.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<IndicesAliasesResponse> listener = (ActionListener<IndicesAliasesResponse>) invocationOnMock.getArguments()[1];
|
||||
IndicesAliasesResponse response = IndicesAliasesAction.INSTANCE.newResponse();
|
||||
response.readFrom(StreamInput.wrap(new byte[] { 1 }));
|
||||
|
||||
assertThat(request.getAliasActions().size(), equalTo(2));
|
||||
assertThat(request.getAliasActions().get(0).actionType(), equalTo(IndicesAliasesRequest.AliasActions.Type.REMOVE_INDEX));
|
||||
assertThat(request.getAliasActions().get(0).indices(), equalTo(new String[] { originalIndexName }));
|
||||
assertThat(request.getAliasActions().get(1).actionType(), equalTo(IndicesAliasesRequest.AliasActions.Type.ADD));
|
||||
assertThat(request.getAliasActions().get(1).indices(), equalTo(new String[] { index.getName() }));
|
||||
assertThat(request.getAliasActions().get(1).aliases(), equalTo(new String[] { originalIndexName }));
|
||||
|
||||
listener.onResponse(response);
|
||||
return null;
|
||||
}).when(indicesClient).aliases(any(), any());
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
|
||||
action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(actionCompleted.get());
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).aliases(any(), any());
|
||||
}
|
||||
|
||||
public void testExecuteAlreadyCompletedAndRunAgain() {
|
||||
String originalIndexName = randomAlphaOfLengthBetween(1, 20);
|
||||
Index index = new Index("shrunk-" + originalIndexName, randomAlphaOfLengthBetween(1, 20));
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.putAlias(AliasMetaData.builder(originalIndexName).build())
|
||||
.settings(settings(Version.CURRENT).put(IndexMetaData.INDEX_SHRINK_SOURCE_NAME_KEY, originalIndexName))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.build();
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
Client client = Mockito.mock(Client.class);
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
|
||||
action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(actionCompleted.get());
|
||||
Mockito.verify(client, Mockito.never()).admin();
|
||||
}
|
||||
|
||||
public void testExecuteOriginalIndexAliasFailure() {
|
||||
String originalIndexName = randomAlphaOfLengthBetween(1, 20);
|
||||
Index index = new Index("shrunk-" + originalIndexName, randomAlphaOfLengthBetween(1, 20));
|
||||
Index targetIndex = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(settings(Version.CURRENT).put(IndexMetaData.INDEX_SHRINK_SOURCE_NAME_KEY, originalIndexName))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.routingTable(RoutingTable.builder()
|
||||
.add(IndexRoutingTable.builder(targetIndex).addShard(
|
||||
TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true,
|
||||
ShardRoutingState.STARTED)))
|
||||
.build())
|
||||
.build();
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<IndicesAliasesResponse> listener = (ActionListener<IndicesAliasesResponse>) invocationOnMock.getArguments()[1];
|
||||
listener.onFailure(new RuntimeException("failed"));
|
||||
return null;
|
||||
}).when(indicesClient).aliases(any(), any());
|
||||
|
||||
SetOnce<Exception> onFailureException = new SetOnce<>();
|
||||
ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
|
||||
action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
throw new AssertionError("Unexpected method call");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
onFailureException.set(e);
|
||||
}
|
||||
});
|
||||
|
||||
assertThat(onFailureException.get().getMessage(), equalTo("failed"));
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).aliases(any(), any());
|
||||
}
|
||||
|
||||
public void testExecuteWithIssuedResizeRequest() {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Index targetIndex = new Index("shrunk-" + index.getName(), randomAlphaOfLengthBetween(1, 20));
|
||||
int numberOfShards = randomIntBetween(1, 5);
|
||||
int numberOfReplicas = randomIntBetween(1, 5);
|
||||
long creationDate = randomNonNegativeLong();
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(settings(Version.CURRENT))
|
||||
.putAlias(AliasMetaData.builder("my_alias"))
|
||||
.creationDate(creationDate)
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(numberOfReplicas).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.routingTable(RoutingTable.builder()
|
||||
.add(IndexRoutingTable.builder(targetIndex).addShard(
|
||||
TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true,
|
||||
ShardRoutingState.STARTED)))
|
||||
.build())
|
||||
.build();
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
|
||||
Settings expectedSettings = Settings.builder().put(IndexMetaData.SETTING_BLOCKS_WRITE, true).build();
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
UpdateSettingsRequest request = (UpdateSettingsRequest) invocationOnMock.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocationOnMock.getArguments()[1];
|
||||
UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, index.getName());
|
||||
listener.onResponse(UpdateSettingsTestHelper.createMockResponse(true));
|
||||
return null;
|
||||
}).when(indicesClient).updateSettings(any(), any());
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
ResizeRequest request = (ResizeRequest) invocationOnMock.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<AcknowledgedResponse> listener = (ActionListener<AcknowledgedResponse>) invocationOnMock.getArguments()[1];
|
||||
assertThat(request.getSourceIndex(), equalTo(index.getName()));
|
||||
assertThat(request.getTargetIndexRequest().aliases(), equalTo(Collections.singleton(new Alias("my_alias"))));
|
||||
assertThat(request.getTargetIndexRequest().settings(), equalTo(Settings.builder()
|
||||
.put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, numberOfShards)
|
||||
.put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, numberOfReplicas)
|
||||
.put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, creationDate).build()));
|
||||
assertThat(request.getTargetIndexRequest().index(), equalTo(targetIndex.getName()));
|
||||
ResizeResponse resizeResponse = ResizeAction.INSTANCE.newResponse();
|
||||
resizeResponse.readFrom(StreamInput.wrap(new byte[] { 1, 1, 1, 1, 1 }));
|
||||
listener.onResponse(resizeResponse);
|
||||
return null;
|
||||
}).when(indicesClient).resizeIndex(any(), any());
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
ShrinkAction action = new ShrinkAction(numberOfShards);
|
||||
|
||||
action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertFalse(actionCompleted.get());
|
||||
|
||||
Mockito.verify(client, Mockito.atLeast(1)).admin();
|
||||
Mockito.verify(adminClient, Mockito.atLeast(1)).indices();
|
||||
Mockito.verify(indicesClient, Mockito.atLeast(1)).updateSettings(any(), any());
|
||||
Mockito.verify(indicesClient, Mockito.atLeast(1)).resizeIndex(any(), any());
|
||||
}
|
||||
|
||||
public void testExecuteWithIssuedResizeRequestFailure() {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Index targetIndex = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(settings(Version.CURRENT))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.routingTable(RoutingTable.builder()
|
||||
.add(IndexRoutingTable.builder(targetIndex).addShard(
|
||||
TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true,
|
||||
ShardRoutingState.STARTED)))
|
||||
.build())
|
||||
.build();
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocationOnMock.getArguments()[1];
|
||||
listener.onResponse(UpdateSettingsTestHelper.createMockResponse(true));
|
||||
return null;
|
||||
}).when(indicesClient).updateSettings(any(), any());
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<AcknowledgedResponse> listener = (ActionListener<AcknowledgedResponse>) invocationOnMock.getArguments()[1];
|
||||
ResizeResponse resizeResponse = ResizeAction.INSTANCE.newResponse();
|
||||
resizeResponse.readFrom(StreamInput.wrap(new byte[] { 0, 1, 1, 1, 1 }));
|
||||
listener.onResponse(resizeResponse);
|
||||
return null;
|
||||
}).when(indicesClient).resizeIndex(any(), any());
|
||||
|
||||
SetOnce<Exception> exceptionReturned = new SetOnce<>();
|
||||
ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
|
||||
action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
throw new AssertionError("Unexpected method call to onSuccess");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
exceptionReturned.set(e);
|
||||
}
|
||||
});
|
||||
|
||||
assertThat(exceptionReturned.get().getMessage(), equalTo("Shrink request failed to be acknowledged"));
|
||||
|
||||
Mockito.verify(client, Mockito.atLeast(1)).admin();
|
||||
Mockito.verify(adminClient, Mockito.atLeast(1)).indices();
|
||||
Mockito.verify(indicesClient, Mockito.atLeast(1)).updateSettings(any(), any());
|
||||
Mockito.verify(indicesClient, Mockito.atLeast(1)).resizeIndex(any(), any());
|
||||
}
|
||||
|
||||
public void testExecuteWithAllShardsAllocatedAndShrunkenIndexSetting() {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Index targetIndex = new Index("shrunk-" + index.getName(), randomAlphaOfLengthBetween(1, 20));
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(settings(Version.CURRENT).put(LifecycleSettings.LIFECYCLE_PHASE, "phase1")
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, "action1").put(LifecycleSettings.LIFECYCLE_NAME, "test"))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
IndexMetaData targetIndexMetaData = IndexMetaData.builder(targetIndex.getName())
|
||||
.settings(settings(Version.CURRENT).put(IndexMetaData.INDEX_SHRINK_SOURCE_NAME_KEY, index.getName()))
|
||||
.numberOfShards(randomIntBetween(1, 3)).numberOfReplicas(indexMetadata.getNumberOfReplicas()).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder()
|
||||
.fPut(index.getName(), indexMetadata).fPut(targetIndex.getName(), targetIndexMetaData);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.routingTable(RoutingTable.builder()
|
||||
.add(IndexRoutingTable.builder(targetIndex).addShard(
|
||||
TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true,
|
||||
ShardRoutingState.STARTED)))
|
||||
.build())
|
||||
.build();
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
|
||||
Settings expectedSettings = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, "test")
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE, "phase1").put(LifecycleSettings.LIFECYCLE_ACTION, "action1").build();
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
UpdateSettingsRequest request = (UpdateSettingsRequest) invocationOnMock.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocationOnMock.getArguments()[1];
|
||||
UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, targetIndex.getName());
|
||||
listener.onResponse(UpdateSettingsTestHelper.createMockResponse(true));
|
||||
return null;
|
||||
}).when(indicesClient).updateSettings(any(), any());
|
||||
|
||||
Mockito.doAnswer(invocationOnMock -> {
|
||||
DeleteIndexRequest request = (DeleteIndexRequest) invocationOnMock.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<DeleteIndexResponse> listener = (ActionListener<DeleteIndexResponse>) invocationOnMock.getArguments()[1];
|
||||
assertNotNull(request);
|
||||
assertEquals(1, request.indices().length);
|
||||
assertEquals(index.getName(), request.indices()[0]);
|
||||
listener.onResponse(null);
|
||||
return null;
|
||||
}).when(indicesClient).delete(any(), any());
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
|
||||
action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertFalse(actionCompleted.get());
|
||||
Mockito.verify(client, Mockito.atLeast(1)).admin();
|
||||
Mockito.verify(adminClient, Mockito.atLeast(1)).indices();
|
||||
Mockito.verify(indicesClient, Mockito.atLeast(1)).updateSettings(any(), any());
|
||||
}
|
||||
|
||||
public void testExecuteWithAllShardsAllocatedAndShrunkenIndexConfigured() {
|
||||
String lifecycleName = randomAlphaOfLengthBetween(5, 10);
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Index targetIndex = new Index("shrunk-" + index.getName(), randomAlphaOfLengthBetween(1, 20));
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(settings(Version.CURRENT).put(LifecycleSettings.LIFECYCLE_PHASE, "phase1")
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, "action1").put(LifecycleSettings.LIFECYCLE_NAME, lifecycleName))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
IndexMetaData targetIndexMetaData = IndexMetaData.builder(targetIndex.getName())
|
||||
.settings(settings(Version.CURRENT)
|
||||
.put(IndexMetaData.INDEX_SHRINK_SOURCE_NAME_KEY, index.getName())
|
||||
.put(LifecycleSettings.LIFECYCLE_NAME_SETTING.getKey(), lifecycleName))
|
||||
.numberOfShards(randomIntBetween(1, 3)).numberOfReplicas(indexMetadata.getNumberOfReplicas()).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder()
|
||||
.fPut(index.getName(), indexMetadata).fPut(targetIndex.getName(), targetIndexMetaData);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.routingTable(RoutingTable.builder()
|
||||
.add(IndexRoutingTable.builder(targetIndex).addShard(
|
||||
TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true,
|
||||
ShardRoutingState.STARTED)))
|
||||
.build())
|
||||
.build();
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
Client client = Mockito.mock(Client.class);
|
||||
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
|
||||
action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertFalse(actionCompleted.get());
|
||||
Mockito.verifyZeroInteractions(client);
|
||||
}
|
||||
|
||||
public void testExecuteWaitingOnAllShardsActive() {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Index targetIndex = new Index("shrunk-" + index.getName(), randomAlphaOfLengthBetween(1, 20));
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(settings(Version.CURRENT))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
IndexMetaData targetIndexMetadata = IndexMetaData.builder(targetIndex.getName())
|
||||
.settings(settings(Version.CURRENT).put(IndexMetaData.INDEX_SHRINK_SOURCE_NAME_KEY, index.getName()))
|
||||
.numberOfShards(1).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata).fPut(targetIndex.getName(), targetIndexMetadata);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
.routingTable(RoutingTable.builder()
|
||||
.add(IndexRoutingTable.builder(targetIndex).addShard(
|
||||
TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true,
|
||||
ShardRoutingState.INITIALIZING)))
|
||||
.build())
|
||||
.build();
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
Client client = Mockito.mock(Client.class);
|
||||
SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
|
||||
action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
actionCompleted.set(completed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertFalse(actionCompleted.get());
|
||||
}
|
||||
|
||||
public void testExecuteIndexAlreadyExists() {
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
Index targetIndex = new Index("shrunk-" + index.getName(), randomAlphaOfLengthBetween(1, 20));
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
.settings(settings(Version.CURRENT))
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
IndexMetaData targetIndexMetadata = IndexMetaData.builder(targetIndex.getName())
|
||||
.settings(settings(Version.CURRENT))
|
||||
.numberOfShards(1).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
indexMetadata).fPut(targetIndex.getName(), targetIndexMetadata);
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE)
|
||||
.metaData(MetaData.builder().indices(indices.build())).build();
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
Client client = Mockito.mock(Client.class);
|
||||
|
||||
SetOnce<Exception> actionFailed = new SetOnce<>();
|
||||
ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
|
||||
action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
throw new AssertionError("Unexpected method call to onSuccess");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
actionFailed.set(e);
|
||||
}
|
||||
});
|
||||
|
||||
assertThat(actionFailed.get().getMessage(), equalTo("Cannot shrink index [" + index.getName() + "]" +
|
||||
" because target index [" + targetIndex.getName() + "] already exists."));
|
||||
}
|
||||
// public void testExecuteSuccessfullyCompleted() {
|
||||
// String originalIndexName = randomAlphaOfLengthBetween(1, 20);
|
||||
// Index index = new Index("shrunk-" + originalIndexName, randomAlphaOfLengthBetween(1, 20));
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
// IndexMetaData originalIndexMetaData = IndexMetaData.builder(originalIndexName)
|
||||
// .settings(settings(Version.CURRENT)).numberOfReplicas(0).numberOfShards(1).build();
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(settings(Version.CURRENT).put(IndexMetaData.INDEX_SHRINK_SOURCE_NAME_KEY, originalIndexName))
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata).fPut(originalIndexName, originalIndexMetaData);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .build();
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// IndicesAliasesRequest request = (IndicesAliasesRequest) invocationOnMock.getArguments()[0];
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<IndicesAliasesResponse> listener = (ActionListener<IndicesAliasesResponse>) invocationOnMock.getArguments()[1];
|
||||
// IndicesAliasesResponse response = IndicesAliasesAction.INSTANCE.newResponse();
|
||||
// response.readFrom(StreamInput.wrap(new byte[] { 1 }));
|
||||
//
|
||||
// assertThat(request.getAliasActions().size(), equalTo(2));
|
||||
// assertThat(request.getAliasActions().get(0).actionType(), equalTo(IndicesAliasesRequest.AliasActions.Type.REMOVE_INDEX));
|
||||
// assertThat(request.getAliasActions().get(0).indices(), equalTo(new String[] { originalIndexName }));
|
||||
// assertThat(request.getAliasActions().get(1).actionType(), equalTo(IndicesAliasesRequest.AliasActions.Type.ADD));
|
||||
// assertThat(request.getAliasActions().get(1).indices(), equalTo(new String[] { index.getName() }));
|
||||
// assertThat(request.getAliasActions().get(1).aliases(), equalTo(new String[] { originalIndexName }));
|
||||
//
|
||||
// listener.onResponse(response);
|
||||
// return null;
|
||||
// }).when(indicesClient).aliases(any(), any());
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
//
|
||||
// action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertTrue(actionCompleted.get());
|
||||
// Mockito.verify(client, Mockito.only()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.only()).aliases(any(), any());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteAlreadyCompletedAndRunAgain() {
|
||||
// String originalIndexName = randomAlphaOfLengthBetween(1, 20);
|
||||
// Index index = new Index("shrunk-" + originalIndexName, randomAlphaOfLengthBetween(1, 20));
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .putAlias(AliasMetaData.builder(originalIndexName).build())
|
||||
// .settings(settings(Version.CURRENT).put(IndexMetaData.INDEX_SHRINK_SOURCE_NAME_KEY, originalIndexName))
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .build();
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
//
|
||||
// action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertTrue(actionCompleted.get());
|
||||
// Mockito.verify(client, Mockito.never()).admin();
|
||||
// }
|
||||
//
|
||||
// public void testExecuteOriginalIndexAliasFailure() {
|
||||
// String originalIndexName = randomAlphaOfLengthBetween(1, 20);
|
||||
// Index index = new Index("shrunk-" + originalIndexName, randomAlphaOfLengthBetween(1, 20));
|
||||
// Index targetIndex = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(settings(Version.CURRENT).put(IndexMetaData.INDEX_SHRINK_SOURCE_NAME_KEY, originalIndexName))
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .routingTable(RoutingTable.builder()
|
||||
// .add(IndexRoutingTable.builder(targetIndex).addShard(
|
||||
// TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true,
|
||||
// ShardRoutingState.STARTED)))
|
||||
// .build())
|
||||
// .build();
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<IndicesAliasesResponse> listener = (ActionListener<IndicesAliasesResponse>) invocationOnMock.getArguments()[1];
|
||||
// listener.onFailure(new RuntimeException("failed"));
|
||||
// return null;
|
||||
// }).when(indicesClient).aliases(any(), any());
|
||||
//
|
||||
// SetOnce<Exception> onFailureException = new SetOnce<>();
|
||||
// ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
//
|
||||
// action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// throw new AssertionError("Unexpected method call");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// onFailureException.set(e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertThat(onFailureException.get().getMessage(), equalTo("failed"));
|
||||
//
|
||||
// Mockito.verify(client, Mockito.only()).admin();
|
||||
// Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.only()).aliases(any(), any());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteWithIssuedResizeRequest() {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Index targetIndex = new Index("shrunk-" + index.getName(), randomAlphaOfLengthBetween(1, 20));
|
||||
// int numberOfShards = randomIntBetween(1, 5);
|
||||
// int numberOfReplicas = randomIntBetween(1, 5);
|
||||
// long creationDate = randomNonNegativeLong();
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(settings(Version.CURRENT))
|
||||
// .putAlias(AliasMetaData.builder("my_alias"))
|
||||
// .creationDate(creationDate)
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(numberOfReplicas).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .routingTable(RoutingTable.builder()
|
||||
// .add(IndexRoutingTable.builder(targetIndex).addShard(
|
||||
// TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true,
|
||||
// ShardRoutingState.STARTED)))
|
||||
// .build())
|
||||
// .build();
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
//
|
||||
// Settings expectedSettings = Settings.builder().put(IndexMetaData.SETTING_BLOCKS_WRITE, true).build();
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// UpdateSettingsRequest request = (UpdateSettingsRequest) invocationOnMock.getArguments()[0];
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocationOnMock.getArguments()[1];
|
||||
// UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, index.getName());
|
||||
// listener.onResponse(UpdateSettingsTestHelper.createMockResponse(true));
|
||||
// return null;
|
||||
// }).when(indicesClient).updateSettings(any(), any());
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// ResizeRequest request = (ResizeRequest) invocationOnMock.getArguments()[0];
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<AcknowledgedResponse> listener = (ActionListener<AcknowledgedResponse>) invocationOnMock.getArguments()[1];
|
||||
// assertThat(request.getSourceIndex(), equalTo(index.getName()));
|
||||
// assertThat(request.getTargetIndexRequest().aliases(), equalTo(Collections.singleton(new Alias("my_alias"))));
|
||||
// assertThat(request.getTargetIndexRequest().settings(), equalTo(Settings.builder()
|
||||
// .put(IndexMetaData.SETTING_NUMBER_OF_SHARDS, numberOfShards)
|
||||
// .put(IndexMetaData.SETTING_NUMBER_OF_REPLICAS, numberOfReplicas)
|
||||
// .put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, creationDate).build()));
|
||||
// assertThat(request.getTargetIndexRequest().index(), equalTo(targetIndex.getName()));
|
||||
// ResizeResponse resizeResponse = ResizeAction.INSTANCE.newResponse();
|
||||
// resizeResponse.readFrom(StreamInput.wrap(new byte[] { 1, 1, 1, 1, 1 }));
|
||||
// listener.onResponse(resizeResponse);
|
||||
// return null;
|
||||
// }).when(indicesClient).resizeIndex(any(), any());
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// ShrinkAction action = new ShrinkAction(numberOfShards);
|
||||
//
|
||||
// action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertFalse(actionCompleted.get());
|
||||
//
|
||||
// Mockito.verify(client, Mockito.atLeast(1)).admin();
|
||||
// Mockito.verify(adminClient, Mockito.atLeast(1)).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.atLeast(1)).updateSettings(any(), any());
|
||||
// Mockito.verify(indicesClient, Mockito.atLeast(1)).resizeIndex(any(), any());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteWithIssuedResizeRequestFailure() {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Index targetIndex = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(settings(Version.CURRENT))
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .routingTable(RoutingTable.builder()
|
||||
// .add(IndexRoutingTable.builder(targetIndex).addShard(
|
||||
// TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true,
|
||||
// ShardRoutingState.STARTED)))
|
||||
// .build())
|
||||
// .build();
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocationOnMock.getArguments()[1];
|
||||
// listener.onResponse(UpdateSettingsTestHelper.createMockResponse(true));
|
||||
// return null;
|
||||
// }).when(indicesClient).updateSettings(any(), any());
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<AcknowledgedResponse> listener = (ActionListener<AcknowledgedResponse>) invocationOnMock.getArguments()[1];
|
||||
// ResizeResponse resizeResponse = ResizeAction.INSTANCE.newResponse();
|
||||
// resizeResponse.readFrom(StreamInput.wrap(new byte[] { 0, 1, 1, 1, 1 }));
|
||||
// listener.onResponse(resizeResponse);
|
||||
// return null;
|
||||
// }).when(indicesClient).resizeIndex(any(), any());
|
||||
//
|
||||
// SetOnce<Exception> exceptionReturned = new SetOnce<>();
|
||||
// ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
//
|
||||
// action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// throw new AssertionError("Unexpected method call to onSuccess");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// exceptionReturned.set(e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertThat(exceptionReturned.get().getMessage(), equalTo("Shrink request failed to be acknowledged"));
|
||||
//
|
||||
// Mockito.verify(client, Mockito.atLeast(1)).admin();
|
||||
// Mockito.verify(adminClient, Mockito.atLeast(1)).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.atLeast(1)).updateSettings(any(), any());
|
||||
// Mockito.verify(indicesClient, Mockito.atLeast(1)).resizeIndex(any(), any());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteWithAllShardsAllocatedAndShrunkenIndexSetting() {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Index targetIndex = new Index("shrunk-" + index.getName(), randomAlphaOfLengthBetween(1, 20));
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(settings(Version.CURRENT).put(LifecycleSettings.LIFECYCLE_PHASE, "phase1")
|
||||
// .put(LifecycleSettings.LIFECYCLE_ACTION, "action1").put(LifecycleSettings.LIFECYCLE_NAME, "test"))
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// IndexMetaData targetIndexMetaData = IndexMetaData.builder(targetIndex.getName())
|
||||
// .settings(settings(Version.CURRENT).put(IndexMetaData.INDEX_SHRINK_SOURCE_NAME_KEY, index.getName()))
|
||||
// .numberOfShards(randomIntBetween(1, 3)).numberOfReplicas(indexMetadata.getNumberOfReplicas()).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder()
|
||||
// .fPut(index.getName(), indexMetadata).fPut(targetIndex.getName(), targetIndexMetaData);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .routingTable(RoutingTable.builder()
|
||||
// .add(IndexRoutingTable.builder(targetIndex).addShard(
|
||||
// TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true,
|
||||
// ShardRoutingState.STARTED)))
|
||||
// .build())
|
||||
// .build();
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
// IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
// Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
// Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
//
|
||||
// Settings expectedSettings = Settings.builder().put(LifecycleSettings.LIFECYCLE_NAME, "test")
|
||||
// .put(LifecycleSettings.LIFECYCLE_PHASE, "phase1").put(LifecycleSettings.LIFECYCLE_ACTION, "action1").build();
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// UpdateSettingsRequest request = (UpdateSettingsRequest) invocationOnMock.getArguments()[0];
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocationOnMock.getArguments()[1];
|
||||
// UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, targetIndex.getName());
|
||||
// listener.onResponse(UpdateSettingsTestHelper.createMockResponse(true));
|
||||
// return null;
|
||||
// }).when(indicesClient).updateSettings(any(), any());
|
||||
//
|
||||
// Mockito.doAnswer(invocationOnMock -> {
|
||||
// DeleteIndexRequest request = (DeleteIndexRequest) invocationOnMock.getArguments()[0];
|
||||
// @SuppressWarnings("unchecked")
|
||||
// ActionListener<DeleteIndexResponse> listener = (ActionListener<DeleteIndexResponse>) invocationOnMock.getArguments()[1];
|
||||
// assertNotNull(request);
|
||||
// assertEquals(1, request.indices().length);
|
||||
// assertEquals(index.getName(), request.indices()[0]);
|
||||
// listener.onResponse(null);
|
||||
// return null;
|
||||
// }).when(indicesClient).delete(any(), any());
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
//
|
||||
// action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertFalse(actionCompleted.get());
|
||||
// Mockito.verify(client, Mockito.atLeast(1)).admin();
|
||||
// Mockito.verify(adminClient, Mockito.atLeast(1)).indices();
|
||||
// Mockito.verify(indicesClient, Mockito.atLeast(1)).updateSettings(any(), any());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteWithAllShardsAllocatedAndShrunkenIndexConfigured() {
|
||||
// String lifecycleName = randomAlphaOfLengthBetween(5, 10);
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Index targetIndex = new Index("shrunk-" + index.getName(), randomAlphaOfLengthBetween(1, 20));
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(settings(Version.CURRENT).put(LifecycleSettings.LIFECYCLE_PHASE, "phase1")
|
||||
// .put(LifecycleSettings.LIFECYCLE_ACTION, "action1").put(LifecycleSettings.LIFECYCLE_NAME, lifecycleName))
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// IndexMetaData targetIndexMetaData = IndexMetaData.builder(targetIndex.getName())
|
||||
// .settings(settings(Version.CURRENT)
|
||||
// .put(IndexMetaData.INDEX_SHRINK_SOURCE_NAME_KEY, index.getName())
|
||||
// .put(LifecycleSettings.LIFECYCLE_NAME_SETTING.getKey(), lifecycleName))
|
||||
// .numberOfShards(randomIntBetween(1, 3)).numberOfReplicas(indexMetadata.getNumberOfReplicas()).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder()
|
||||
// .fPut(index.getName(), indexMetadata).fPut(targetIndex.getName(), targetIndexMetaData);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .routingTable(RoutingTable.builder()
|
||||
// .add(IndexRoutingTable.builder(targetIndex).addShard(
|
||||
// TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true,
|
||||
// ShardRoutingState.STARTED)))
|
||||
// .build())
|
||||
// .build();
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
//
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
//
|
||||
// action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertFalse(actionCompleted.get());
|
||||
// Mockito.verifyZeroInteractions(client);
|
||||
// }
|
||||
//
|
||||
// public void testExecuteWaitingOnAllShardsActive() {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Index targetIndex = new Index("shrunk-" + index.getName(), randomAlphaOfLengthBetween(1, 20));
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(settings(Version.CURRENT))
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// IndexMetaData targetIndexMetadata = IndexMetaData.builder(targetIndex.getName())
|
||||
// .settings(settings(Version.CURRENT).put(IndexMetaData.INDEX_SHRINK_SOURCE_NAME_KEY, index.getName()))
|
||||
// .numberOfShards(1).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata).fPut(targetIndex.getName(), targetIndexMetadata);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE).metaData(MetaData.builder().indices(indices.build()))
|
||||
// .routingTable(RoutingTable.builder()
|
||||
// .add(IndexRoutingTable.builder(targetIndex).addShard(
|
||||
// TestShardRouting.newShardRouting(new ShardId(index, 0), "node1", true,
|
||||
// ShardRoutingState.INITIALIZING)))
|
||||
// .build())
|
||||
// .build();
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
// SetOnce<Boolean> actionCompleted = new SetOnce<>();
|
||||
// ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
//
|
||||
// action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// actionCompleted.set(completed);
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// throw new AssertionError("Unexpected method call", e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertFalse(actionCompleted.get());
|
||||
// }
|
||||
//
|
||||
// public void testExecuteIndexAlreadyExists() {
|
||||
// Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
// Index targetIndex = new Index("shrunk-" + index.getName(), randomAlphaOfLengthBetween(1, 20));
|
||||
// ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
// IndexMetaData indexMetadata = IndexMetaData.builder(index.getName())
|
||||
// .settings(settings(Version.CURRENT))
|
||||
// .numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// IndexMetaData targetIndexMetadata = IndexMetaData.builder(targetIndex.getName())
|
||||
// .settings(settings(Version.CURRENT))
|
||||
// .numberOfShards(1).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder().fPut(index.getName(),
|
||||
// indexMetadata).fPut(targetIndex.getName(), targetIndexMetadata);
|
||||
// ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE)
|
||||
// .metaData(MetaData.builder().indices(indices.build())).build();
|
||||
// Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
// Client client = Mockito.mock(Client.class);
|
||||
//
|
||||
// SetOnce<Exception> actionFailed = new SetOnce<>();
|
||||
// ShrinkAction action = new ShrinkAction(randomIntBetween(1, 10));
|
||||
//
|
||||
// action.execute(index, client, clusterService, new LifecycleAction.Listener() {
|
||||
// @Override
|
||||
// public void onSuccess(boolean completed) {
|
||||
// throw new AssertionError("Unexpected method call to onSuccess");
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public void onFailure(Exception e) {
|
||||
// actionFailed.set(e);
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// assertThat(actionFailed.get().getMessage(), equalTo("Cannot shrink index [" + index.getName() + "]" +
|
||||
// " because target index [" + targetIndex.getName() + "] already exists."));
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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.indexlifecycle;
|
||||
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
public class StepTests extends ESTestCase {
|
||||
|
||||
public void test() {
|
||||
}
|
||||
}
|
|
@ -36,10 +36,10 @@ public class TestLifecycleType implements LifecycleType {
|
|||
return TYPE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public NextActionProvider getActionProvider(IndexLifecycleContext context, Phase phase) {
|
||||
return a -> Optional.ofNullable(phase.getActions().entrySet().iterator().next()).map(Map.Entry::getValue).orElse(null);
|
||||
}
|
||||
// @Override
|
||||
// public NextActionProvider getActionProvider(IndexLifecycleContext context, Phase phase) {
|
||||
// return a -> Optional.ofNullable(phase.getActions().entrySet().iterator().next()).map(Map.Entry::getValue).orElse(null);
|
||||
// }
|
||||
|
||||
@Override
|
||||
public Phase getFirstPhase(Map<String, Phase> phases) {
|
||||
|
|
|
@ -47,357 +47,361 @@ public class TimeseriesLifecycleTypeTests extends ESTestCase {
|
|||
private static final ShrinkAction TEST_SHRINK_ACTION = new ShrinkAction(1);
|
||||
private static final LongSupplier TEST_NOW_SUPPLIER = () -> 0L;
|
||||
|
||||
public void testGetFirstPhase() {
|
||||
Map<String, Phase> phases = new HashMap<>();
|
||||
Phase expectedFirstPhase = null;
|
||||
for (String phaseName : Arrays.asList("hot", "warm", "cold", "delete")) {
|
||||
if (randomBoolean()) {
|
||||
Phase phase = new Phase(phaseName, TimeValue.MINUS_ONE, Collections.emptyMap());
|
||||
phases.put(phaseName, phase);
|
||||
if (expectedFirstPhase == null) {
|
||||
expectedFirstPhase = phase;
|
||||
}
|
||||
}
|
||||
}
|
||||
TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
assertThat(policy.getFirstPhase(phases), equalTo(expectedFirstPhase));
|
||||
}
|
||||
|
||||
public void testGetNextPhase() {
|
||||
for (int runs = 0; runs < 20; runs++) {
|
||||
Map<String, Phase> phases = new HashMap<>();
|
||||
List<Phase> phasesInOrder = new ArrayList<>();
|
||||
for (String phase : VALID_PHASES) {
|
||||
if (randomBoolean()) {
|
||||
Phase phaseToAdd = new Phase(phase, TimeValue.MINUS_ONE, Collections.emptyMap());
|
||||
phases.put(phase, phaseToAdd);
|
||||
phasesInOrder.add(phaseToAdd);
|
||||
}
|
||||
}
|
||||
TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
assertThat(policy.nextPhase(phases, null), equalTo(policy.getFirstPhase(phases)));
|
||||
for (int i = 0; i < phasesInOrder.size() - 1; i++) {
|
||||
assertThat(policy.nextPhase(phases, phasesInOrder.get(i)), equalTo(phasesInOrder.get(i + 1)));
|
||||
}
|
||||
if (phasesInOrder.isEmpty() == false) {
|
||||
assertNull(policy.nextPhase(phases, phasesInOrder.get(phasesInOrder.size() - 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void testValidatePhases() {
|
||||
boolean invalid = randomBoolean();
|
||||
String phaseName = randomFrom("hot", "warm", "cold", "delete");
|
||||
if (invalid) {
|
||||
phaseName += randomAlphaOfLength(5);
|
||||
}
|
||||
Map<String, Phase> phases = Collections.singletonMap(phaseName,
|
||||
new Phase(phaseName, TimeValue.ZERO, Collections.emptyMap()));
|
||||
if (invalid) {
|
||||
Exception e = expectThrows(IllegalArgumentException.class, () -> TimeseriesLifecycleType.INSTANCE.validate(phases.values()));
|
||||
assertThat(e.getMessage(), equalTo("Timeseries lifecycle does not support phase [" + phaseName + "]"));
|
||||
} else {
|
||||
TimeseriesLifecycleType.INSTANCE.validate(phases.values());
|
||||
}
|
||||
}
|
||||
|
||||
public void testValidateHotPhase() {
|
||||
LifecycleAction invalidAction = null;
|
||||
Map<String, LifecycleAction> actions = VALID_HOT_ACTIONS
|
||||
.stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
if (randomBoolean()) {
|
||||
invalidAction = getTestAction(randomFrom("allocate", "forcemerge", "delete", "replicas", "shrink"));
|
||||
actions.put(invalidAction.getWriteableName(), invalidAction);
|
||||
}
|
||||
Map<String, Phase> hotPhase = Collections.singletonMap("hot",
|
||||
new Phase("hot", TimeValue.ZERO, actions));
|
||||
|
||||
if (invalidAction != null) {
|
||||
Exception e = expectThrows(IllegalArgumentException.class,
|
||||
() -> TimeseriesLifecycleType.INSTANCE.validate(hotPhase.values()));
|
||||
assertThat(e.getMessage(),
|
||||
equalTo("invalid action [" + invalidAction.getWriteableName() + "] defined in phase [hot]"));
|
||||
} else {
|
||||
TimeseriesLifecycleType.INSTANCE.validate(hotPhase.values());
|
||||
}
|
||||
}
|
||||
|
||||
public void testValidateWarmPhase() {
|
||||
LifecycleAction invalidAction = null;
|
||||
Map<String, LifecycleAction> actions = randomSubsetOf(VALID_WARM_ACTIONS)
|
||||
.stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
if (randomBoolean()) {
|
||||
invalidAction = getTestAction(randomFrom("rollover", "delete"));
|
||||
actions.put(invalidAction.getWriteableName(), invalidAction);
|
||||
}
|
||||
Map<String, Phase> warmPhase = Collections.singletonMap("warm",
|
||||
new Phase("warm", TimeValue.ZERO, actions));
|
||||
|
||||
if (invalidAction != null) {
|
||||
Exception e = expectThrows(IllegalArgumentException.class,
|
||||
() -> TimeseriesLifecycleType.INSTANCE.validate(warmPhase.values()));
|
||||
assertThat(e.getMessage(),
|
||||
equalTo("invalid action [" + invalidAction.getWriteableName() + "] defined in phase [warm]"));
|
||||
} else {
|
||||
TimeseriesLifecycleType.INSTANCE.validate(warmPhase.values());
|
||||
}
|
||||
}
|
||||
|
||||
public void testValidateColdPhase() {
|
||||
LifecycleAction invalidAction = null;
|
||||
Map<String, LifecycleAction> actions = randomSubsetOf(VALID_COLD_ACTIONS)
|
||||
.stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
if (randomBoolean()) {
|
||||
invalidAction = getTestAction(randomFrom("rollover", "delete", "forcemerge", "shrink"));
|
||||
actions.put(invalidAction.getWriteableName(), invalidAction);
|
||||
}
|
||||
Map<String, Phase> coldPhase = Collections.singletonMap("cold",
|
||||
new Phase("cold", TimeValue.ZERO, actions));
|
||||
|
||||
if (invalidAction != null) {
|
||||
Exception e = expectThrows(IllegalArgumentException.class,
|
||||
() -> TimeseriesLifecycleType.INSTANCE.validate(coldPhase.values()));
|
||||
assertThat(e.getMessage(),
|
||||
equalTo("invalid action [" + invalidAction.getWriteableName() + "] defined in phase [cold]"));
|
||||
} else {
|
||||
TimeseriesLifecycleType.INSTANCE.validate(coldPhase.values());
|
||||
}
|
||||
}
|
||||
|
||||
public void testValidateDeletePhase() {
|
||||
LifecycleAction invalidAction = null;
|
||||
Map<String, LifecycleAction> actions = VALID_DELETE_ACTIONS
|
||||
.stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
if (randomBoolean()) {
|
||||
invalidAction = getTestAction(randomFrom("allocate", "rollover", "replicas", "forcemerge", "shrink"));
|
||||
actions.put(invalidAction.getWriteableName(), invalidAction);
|
||||
}
|
||||
Map<String, Phase> deletePhase = Collections.singletonMap("delete",
|
||||
new Phase("delete", TimeValue.ZERO, actions));
|
||||
|
||||
if (invalidAction != null) {
|
||||
Exception e = expectThrows(IllegalArgumentException.class,
|
||||
() -> TimeseriesLifecycleType.INSTANCE.validate(deletePhase.values()));
|
||||
assertThat(e.getMessage(),
|
||||
equalTo("invalid action [" + invalidAction.getWriteableName() + "] defined in phase [delete]"));
|
||||
} else {
|
||||
TimeseriesLifecycleType.INSTANCE.validate(deletePhase.values());
|
||||
}
|
||||
}
|
||||
|
||||
public void testHotActionProvider() {
|
||||
String indexName = randomAlphaOfLengthBetween(1, 10);
|
||||
Map<String, LifecycleAction> actions = VALID_HOT_ACTIONS
|
||||
.stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
Phase hotPhase = new Phase("hot", TimeValue.ZERO, actions);
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, "", "",
|
||||
0, TEST_NOW_SUPPLIER) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
assertSame(hotPhase, phase);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, hotPhase);
|
||||
assertThat(provider.next(null), equalTo(TEST_ROLLOVER_ACTION));
|
||||
assertNull(provider.next(TEST_ROLLOVER_ACTION));
|
||||
}
|
||||
|
||||
public void testWarmActionProviderWithAllActionsAndReplicasFirst() {
|
||||
String indexName = randomAlphaOfLengthBetween(1, 10);
|
||||
Map<String, LifecycleAction> actions = VALID_WARM_ACTIONS
|
||||
.stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
actions.put(ReplicasAction.NAME, TEST_REPLICAS_ACTION);
|
||||
Phase warmPhase = new Phase("warm", TimeValue.ZERO, actions);
|
||||
MockIndexLifecycleContext context =new MockIndexLifecycleContext(indexName, "", "",
|
||||
TEST_REPLICAS_ACTION.getNumberOfReplicas() + 1, TEST_NOW_SUPPLIER) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
assertSame(warmPhase, phase);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, warmPhase);
|
||||
if (actions.size() > 1) {
|
||||
int actionCount = 1;
|
||||
LifecycleAction current = provider.next(null);
|
||||
assertThat(current, equalTo(TEST_REPLICAS_ACTION));
|
||||
while (actionCount++ < actions.size()) {
|
||||
current = provider.next(current);
|
||||
}
|
||||
assertNull(provider.next(current));
|
||||
assertThat(current, equalTo(TEST_FORCE_MERGE_ACTION));
|
||||
} else {
|
||||
assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
}
|
||||
public void testStub() {
|
||||
|
||||
}
|
||||
|
||||
public void testWarmActionProviderReplicasActionSortOrder() {
|
||||
String indexName = randomAlphaOfLengthBetween(1, 10);
|
||||
Map<String, LifecycleAction> actions = randomSubsetOf(VALID_WARM_ACTIONS)
|
||||
.stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
actions.put(ReplicasAction.NAME, TEST_REPLICAS_ACTION);
|
||||
Phase warmPhase = new Phase("warm", TimeValue.ZERO, actions);
|
||||
MockIndexLifecycleContext context =new MockIndexLifecycleContext(indexName, "", "",
|
||||
TEST_REPLICAS_ACTION.getNumberOfReplicas() + 1, TEST_NOW_SUPPLIER) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
assertSame(warmPhase, phase);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, warmPhase);
|
||||
assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
context = new MockIndexLifecycleContext(indexName, "", "",
|
||||
TEST_REPLICAS_ACTION.getNumberOfReplicas() - 1, TEST_NOW_SUPPLIER) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
assertSame(warmPhase, phase);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
provider = policy.getActionProvider(context, warmPhase);
|
||||
if (actions.size() > 1) {
|
||||
int actionCount = 1;
|
||||
LifecycleAction current = provider.next(null);
|
||||
assertThat(current, not(equalTo(TEST_REPLICAS_ACTION)));
|
||||
while (actionCount++ < actions.size()) {
|
||||
current = provider.next(current);
|
||||
}
|
||||
assertNull(provider.next(current));
|
||||
assertThat(current, equalTo(TEST_REPLICAS_ACTION));
|
||||
} else {
|
||||
assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
}
|
||||
}
|
||||
|
||||
public void testColdActionProviderAllActions() {
|
||||
String indexName = randomAlphaOfLengthBetween(1, 10);
|
||||
Map<String, LifecycleAction> actions = VALID_COLD_ACTIONS
|
||||
.stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
actions.put(ReplicasAction.NAME, TEST_REPLICAS_ACTION);
|
||||
Phase coldPhase = new Phase("cold", TimeValue.ZERO, actions);
|
||||
MockIndexLifecycleContext context =new MockIndexLifecycleContext(indexName, "", "",
|
||||
TEST_REPLICAS_ACTION.getNumberOfReplicas() - 1, TEST_NOW_SUPPLIER) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
assertSame(coldPhase, phase);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, coldPhase);
|
||||
if (actions.size() > 1) {
|
||||
LifecycleAction current = provider.next(null);
|
||||
assertThat(current, equalTo(TEST_ALLOCATE_ACTION));
|
||||
assertThat(provider.next(current), equalTo(TEST_REPLICAS_ACTION));
|
||||
} else {
|
||||
assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
}
|
||||
|
||||
context = new MockIndexLifecycleContext(indexName, "", "",
|
||||
TEST_REPLICAS_ACTION.getNumberOfReplicas() + 1, TEST_NOW_SUPPLIER) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
assertSame(coldPhase, phase);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
provider = policy.getActionProvider(context, coldPhase);
|
||||
if (actions.size() > 1) {
|
||||
LifecycleAction current = provider.next(null);
|
||||
assertThat(current, equalTo(TEST_REPLICAS_ACTION));
|
||||
assertThat(provider.next(current), equalTo(TEST_ALLOCATE_ACTION));
|
||||
} else {
|
||||
assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
}
|
||||
}
|
||||
|
||||
public void testColdActionProviderReplicasActionSortOrder() {
|
||||
String indexName = randomAlphaOfLengthBetween(1, 10);
|
||||
Map<String, LifecycleAction> actions = randomSubsetOf(VALID_COLD_ACTIONS)
|
||||
.stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
actions.put(ReplicasAction.NAME, TEST_REPLICAS_ACTION);
|
||||
Phase coldPhase = new Phase("cold", TimeValue.ZERO, actions);
|
||||
MockIndexLifecycleContext context =new MockIndexLifecycleContext(indexName, "", "",
|
||||
TEST_REPLICAS_ACTION.getNumberOfReplicas() + 1, TEST_NOW_SUPPLIER) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
assertSame(coldPhase, phase);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, coldPhase);
|
||||
assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
context = new MockIndexLifecycleContext(indexName, "", "",
|
||||
TEST_REPLICAS_ACTION.getNumberOfReplicas() - 1, TEST_NOW_SUPPLIER) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
assertSame(coldPhase, phase);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
provider = policy.getActionProvider(context, coldPhase);
|
||||
if (actions.size() > 1) {
|
||||
LifecycleAction current = provider.next(null);
|
||||
assertThat(current, equalTo(TEST_ALLOCATE_ACTION));
|
||||
assertThat(provider.next(current), equalTo(TEST_REPLICAS_ACTION));
|
||||
} else {
|
||||
assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
}
|
||||
}
|
||||
|
||||
public void testDeleteActionProvider() {
|
||||
String indexName = randomAlphaOfLengthBetween(1, 10);
|
||||
Map<String, LifecycleAction> actions = VALID_DELETE_ACTIONS
|
||||
.stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
Phase deletePhase = new Phase("delete", TimeValue.ZERO, actions);
|
||||
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, "", "",
|
||||
0, TEST_NOW_SUPPLIER) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
assertSame(deletePhase, phase);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, deletePhase);
|
||||
assertThat(provider.next(null), equalTo(TEST_DELETE_ACTION));
|
||||
assertNull(provider.next(TEST_DELETE_ACTION));
|
||||
}
|
||||
|
||||
|
||||
private LifecycleAction getTestAction(String actionName) {
|
||||
switch (actionName) {
|
||||
case AllocateAction.NAME:
|
||||
return TEST_ALLOCATE_ACTION;
|
||||
case DeleteAction.NAME:
|
||||
return TEST_DELETE_ACTION;
|
||||
case ForceMergeAction.NAME:
|
||||
return TEST_FORCE_MERGE_ACTION;
|
||||
case ReplicasAction.NAME:
|
||||
return TEST_REPLICAS_ACTION;
|
||||
case RolloverAction.NAME:
|
||||
return TEST_ROLLOVER_ACTION;
|
||||
case ShrinkAction.NAME:
|
||||
return TEST_SHRINK_ACTION;
|
||||
default:
|
||||
throw new IllegalArgumentException("unsupported timeseries phase action [" + actionName + "]");
|
||||
}
|
||||
}
|
||||
// public void testGetFirstPhase() {
|
||||
// Map<String, Phase> phases = new HashMap<>();
|
||||
// Phase expectedFirstPhase = null;
|
||||
// for (String phaseName : Arrays.asList("hot", "warm", "cold", "delete")) {
|
||||
// if (randomBoolean()) {
|
||||
// Phase phase = new Phase(phaseName, TimeValue.MINUS_ONE, Collections.emptyMap());
|
||||
// phases.put(phaseName, phase);
|
||||
// if (expectedFirstPhase == null) {
|
||||
// expectedFirstPhase = phase;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
// assertThat(policy.getFirstPhase(phases), equalTo(expectedFirstPhase));
|
||||
// }
|
||||
//
|
||||
// public void testGetNextPhase() {
|
||||
// for (int runs = 0; runs < 20; runs++) {
|
||||
// Map<String, Phase> phases = new HashMap<>();
|
||||
// List<Phase> phasesInOrder = new ArrayList<>();
|
||||
// for (String phase : VALID_PHASES) {
|
||||
// if (randomBoolean()) {
|
||||
// Phase phaseToAdd = new Phase(phase, TimeValue.MINUS_ONE, Collections.emptyMap());
|
||||
// phases.put(phase, phaseToAdd);
|
||||
// phasesInOrder.add(phaseToAdd);
|
||||
// }
|
||||
// }
|
||||
// TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
// assertThat(policy.nextPhase(phases, null), equalTo(policy.getFirstPhase(phases)));
|
||||
// for (int i = 0; i < phasesInOrder.size() - 1; i++) {
|
||||
// assertThat(policy.nextPhase(phases, phasesInOrder.get(i)), equalTo(phasesInOrder.get(i + 1)));
|
||||
// }
|
||||
// if (phasesInOrder.isEmpty() == false) {
|
||||
// assertNull(policy.nextPhase(phases, phasesInOrder.get(phasesInOrder.size() - 1)));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void testValidatePhases() {
|
||||
// boolean invalid = randomBoolean();
|
||||
// String phaseName = randomFrom("hot", "warm", "cold", "delete");
|
||||
// if (invalid) {
|
||||
// phaseName += randomAlphaOfLength(5);
|
||||
// }
|
||||
// Map<String, Phase> phases = Collections.singletonMap(phaseName,
|
||||
// new Phase(phaseName, TimeValue.ZERO, Collections.emptyMap()));
|
||||
// if (invalid) {
|
||||
// Exception e = expectThrows(IllegalArgumentException.class, () -> TimeseriesLifecycleType.INSTANCE.validate(phases.values()));
|
||||
// assertThat(e.getMessage(), equalTo("Timeseries lifecycle does not support phase [" + phaseName + "]"));
|
||||
// } else {
|
||||
// TimeseriesLifecycleType.INSTANCE.validate(phases.values());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void testValidateHotPhase() {
|
||||
// LifecycleAction invalidAction = null;
|
||||
// Map<String, LifecycleAction> actions = VALID_HOT_ACTIONS
|
||||
// .stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
// if (randomBoolean()) {
|
||||
// invalidAction = getTestAction(randomFrom("allocate", "forcemerge", "delete", "replicas", "shrink"));
|
||||
// actions.put(invalidAction.getWriteableName(), invalidAction);
|
||||
// }
|
||||
// Map<String, Phase> hotPhase = Collections.singletonMap("hot",
|
||||
// new Phase("hot", TimeValue.ZERO, actions));
|
||||
//
|
||||
// if (invalidAction != null) {
|
||||
// Exception e = expectThrows(IllegalArgumentException.class,
|
||||
// () -> TimeseriesLifecycleType.INSTANCE.validate(hotPhase.values()));
|
||||
// assertThat(e.getMessage(),
|
||||
// equalTo("invalid action [" + invalidAction.getWriteableName() + "] defined in phase [hot]"));
|
||||
// } else {
|
||||
// TimeseriesLifecycleType.INSTANCE.validate(hotPhase.values());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void testValidateWarmPhase() {
|
||||
// LifecycleAction invalidAction = null;
|
||||
// Map<String, LifecycleAction> actions = randomSubsetOf(VALID_WARM_ACTIONS)
|
||||
// .stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
// if (randomBoolean()) {
|
||||
// invalidAction = getTestAction(randomFrom("rollover", "delete"));
|
||||
// actions.put(invalidAction.getWriteableName(), invalidAction);
|
||||
// }
|
||||
// Map<String, Phase> warmPhase = Collections.singletonMap("warm",
|
||||
// new Phase("warm", TimeValue.ZERO, actions));
|
||||
//
|
||||
// if (invalidAction != null) {
|
||||
// Exception e = expectThrows(IllegalArgumentException.class,
|
||||
// () -> TimeseriesLifecycleType.INSTANCE.validate(warmPhase.values()));
|
||||
// assertThat(e.getMessage(),
|
||||
// equalTo("invalid action [" + invalidAction.getWriteableName() + "] defined in phase [warm]"));
|
||||
// } else {
|
||||
// TimeseriesLifecycleType.INSTANCE.validate(warmPhase.values());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void testValidateColdPhase() {
|
||||
// LifecycleAction invalidAction = null;
|
||||
// Map<String, LifecycleAction> actions = randomSubsetOf(VALID_COLD_ACTIONS)
|
||||
// .stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
// if (randomBoolean()) {
|
||||
// invalidAction = getTestAction(randomFrom("rollover", "delete", "forcemerge", "shrink"));
|
||||
// actions.put(invalidAction.getWriteableName(), invalidAction);
|
||||
// }
|
||||
// Map<String, Phase> coldPhase = Collections.singletonMap("cold",
|
||||
// new Phase("cold", TimeValue.ZERO, actions));
|
||||
//
|
||||
// if (invalidAction != null) {
|
||||
// Exception e = expectThrows(IllegalArgumentException.class,
|
||||
// () -> TimeseriesLifecycleType.INSTANCE.validate(coldPhase.values()));
|
||||
// assertThat(e.getMessage(),
|
||||
// equalTo("invalid action [" + invalidAction.getWriteableName() + "] defined in phase [cold]"));
|
||||
// } else {
|
||||
// TimeseriesLifecycleType.INSTANCE.validate(coldPhase.values());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void testValidateDeletePhase() {
|
||||
// LifecycleAction invalidAction = null;
|
||||
// Map<String, LifecycleAction> actions = VALID_DELETE_ACTIONS
|
||||
// .stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
// if (randomBoolean()) {
|
||||
// invalidAction = getTestAction(randomFrom("allocate", "rollover", "replicas", "forcemerge", "shrink"));
|
||||
// actions.put(invalidAction.getWriteableName(), invalidAction);
|
||||
// }
|
||||
// Map<String, Phase> deletePhase = Collections.singletonMap("delete",
|
||||
// new Phase("delete", TimeValue.ZERO, actions));
|
||||
//
|
||||
// if (invalidAction != null) {
|
||||
// Exception e = expectThrows(IllegalArgumentException.class,
|
||||
// () -> TimeseriesLifecycleType.INSTANCE.validate(deletePhase.values()));
|
||||
// assertThat(e.getMessage(),
|
||||
// equalTo("invalid action [" + invalidAction.getWriteableName() + "] defined in phase [delete]"));
|
||||
// } else {
|
||||
// TimeseriesLifecycleType.INSTANCE.validate(deletePhase.values());
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void testHotActionProvider() {
|
||||
// String indexName = randomAlphaOfLengthBetween(1, 10);
|
||||
// Map<String, LifecycleAction> actions = VALID_HOT_ACTIONS
|
||||
// .stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
// Phase hotPhase = new Phase("hot", TimeValue.ZERO, actions);
|
||||
// MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, "", "",
|
||||
// 0, TEST_NOW_SUPPLIER) {
|
||||
//
|
||||
// @Override
|
||||
// public boolean canExecute(Phase phase) {
|
||||
// assertSame(hotPhase, phase);
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
// TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
// LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, hotPhase);
|
||||
// assertThat(provider.next(null), equalTo(TEST_ROLLOVER_ACTION));
|
||||
// assertNull(provider.next(TEST_ROLLOVER_ACTION));
|
||||
// }
|
||||
//
|
||||
// public void testWarmActionProviderWithAllActionsAndReplicasFirst() {
|
||||
// String indexName = randomAlphaOfLengthBetween(1, 10);
|
||||
// Map<String, LifecycleAction> actions = VALID_WARM_ACTIONS
|
||||
// .stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
// actions.put(ReplicasAction.NAME, TEST_REPLICAS_ACTION);
|
||||
// Phase warmPhase = new Phase("warm", TimeValue.ZERO, actions);
|
||||
// MockIndexLifecycleContext context =new MockIndexLifecycleContext(indexName, "", "",
|
||||
// TEST_REPLICAS_ACTION.getNumberOfReplicas() + 1, TEST_NOW_SUPPLIER) {
|
||||
//
|
||||
// @Override
|
||||
// public boolean canExecute(Phase phase) {
|
||||
// assertSame(warmPhase, phase);
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
// TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
// LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, warmPhase);
|
||||
// if (actions.size() > 1) {
|
||||
// int actionCount = 1;
|
||||
// LifecycleAction current = provider.next(null);
|
||||
// assertThat(current, equalTo(TEST_REPLICAS_ACTION));
|
||||
// while (actionCount++ < actions.size()) {
|
||||
// current = provider.next(current);
|
||||
// }
|
||||
// assertNull(provider.next(current));
|
||||
// assertThat(current, equalTo(TEST_FORCE_MERGE_ACTION));
|
||||
// } else {
|
||||
// assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// public void testWarmActionProviderReplicasActionSortOrder() {
|
||||
// String indexName = randomAlphaOfLengthBetween(1, 10);
|
||||
// Map<String, LifecycleAction> actions = randomSubsetOf(VALID_WARM_ACTIONS)
|
||||
// .stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
// actions.put(ReplicasAction.NAME, TEST_REPLICAS_ACTION);
|
||||
// Phase warmPhase = new Phase("warm", TimeValue.ZERO, actions);
|
||||
// MockIndexLifecycleContext context =new MockIndexLifecycleContext(indexName, "", "",
|
||||
// TEST_REPLICAS_ACTION.getNumberOfReplicas() + 1, TEST_NOW_SUPPLIER) {
|
||||
//
|
||||
// @Override
|
||||
// public boolean canExecute(Phase phase) {
|
||||
// assertSame(warmPhase, phase);
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
// TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
// LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, warmPhase);
|
||||
// assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
// context = new MockIndexLifecycleContext(indexName, "", "",
|
||||
// TEST_REPLICAS_ACTION.getNumberOfReplicas() - 1, TEST_NOW_SUPPLIER) {
|
||||
//
|
||||
// @Override
|
||||
// public boolean canExecute(Phase phase) {
|
||||
// assertSame(warmPhase, phase);
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
// provider = policy.getActionProvider(context, warmPhase);
|
||||
// if (actions.size() > 1) {
|
||||
// int actionCount = 1;
|
||||
// LifecycleAction current = provider.next(null);
|
||||
// assertThat(current, not(equalTo(TEST_REPLICAS_ACTION)));
|
||||
// while (actionCount++ < actions.size()) {
|
||||
// current = provider.next(current);
|
||||
// }
|
||||
// assertNull(provider.next(current));
|
||||
// assertThat(current, equalTo(TEST_REPLICAS_ACTION));
|
||||
// } else {
|
||||
// assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void testColdActionProviderAllActions() {
|
||||
// String indexName = randomAlphaOfLengthBetween(1, 10);
|
||||
// Map<String, LifecycleAction> actions = VALID_COLD_ACTIONS
|
||||
// .stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
// actions.put(ReplicasAction.NAME, TEST_REPLICAS_ACTION);
|
||||
// Phase coldPhase = new Phase("cold", TimeValue.ZERO, actions);
|
||||
// MockIndexLifecycleContext context =new MockIndexLifecycleContext(indexName, "", "",
|
||||
// TEST_REPLICAS_ACTION.getNumberOfReplicas() - 1, TEST_NOW_SUPPLIER) {
|
||||
//
|
||||
// @Override
|
||||
// public boolean canExecute(Phase phase) {
|
||||
// assertSame(coldPhase, phase);
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
// TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
// LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, coldPhase);
|
||||
// if (actions.size() > 1) {
|
||||
// LifecycleAction current = provider.next(null);
|
||||
// assertThat(current, equalTo(TEST_ALLOCATE_ACTION));
|
||||
// assertThat(provider.next(current), equalTo(TEST_REPLICAS_ACTION));
|
||||
// } else {
|
||||
// assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
// }
|
||||
//
|
||||
// context = new MockIndexLifecycleContext(indexName, "", "",
|
||||
// TEST_REPLICAS_ACTION.getNumberOfReplicas() + 1, TEST_NOW_SUPPLIER) {
|
||||
//
|
||||
// @Override
|
||||
// public boolean canExecute(Phase phase) {
|
||||
// assertSame(coldPhase, phase);
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
// provider = policy.getActionProvider(context, coldPhase);
|
||||
// if (actions.size() > 1) {
|
||||
// LifecycleAction current = provider.next(null);
|
||||
// assertThat(current, equalTo(TEST_REPLICAS_ACTION));
|
||||
// assertThat(provider.next(current), equalTo(TEST_ALLOCATE_ACTION));
|
||||
// } else {
|
||||
// assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void testColdActionProviderReplicasActionSortOrder() {
|
||||
// String indexName = randomAlphaOfLengthBetween(1, 10);
|
||||
// Map<String, LifecycleAction> actions = randomSubsetOf(VALID_COLD_ACTIONS)
|
||||
// .stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
// actions.put(ReplicasAction.NAME, TEST_REPLICAS_ACTION);
|
||||
// Phase coldPhase = new Phase("cold", TimeValue.ZERO, actions);
|
||||
// MockIndexLifecycleContext context =new MockIndexLifecycleContext(indexName, "", "",
|
||||
// TEST_REPLICAS_ACTION.getNumberOfReplicas() + 1, TEST_NOW_SUPPLIER) {
|
||||
//
|
||||
// @Override
|
||||
// public boolean canExecute(Phase phase) {
|
||||
// assertSame(coldPhase, phase);
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
// TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
// LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, coldPhase);
|
||||
// assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
// context = new MockIndexLifecycleContext(indexName, "", "",
|
||||
// TEST_REPLICAS_ACTION.getNumberOfReplicas() - 1, TEST_NOW_SUPPLIER) {
|
||||
//
|
||||
// @Override
|
||||
// public boolean canExecute(Phase phase) {
|
||||
// assertSame(coldPhase, phase);
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
// provider = policy.getActionProvider(context, coldPhase);
|
||||
// if (actions.size() > 1) {
|
||||
// LifecycleAction current = provider.next(null);
|
||||
// assertThat(current, equalTo(TEST_ALLOCATE_ACTION));
|
||||
// assertThat(provider.next(current), equalTo(TEST_REPLICAS_ACTION));
|
||||
// } else {
|
||||
// assertThat(provider.next(null), equalTo(TEST_REPLICAS_ACTION));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// public void testDeleteActionProvider() {
|
||||
// String indexName = randomAlphaOfLengthBetween(1, 10);
|
||||
// Map<String, LifecycleAction> actions = VALID_DELETE_ACTIONS
|
||||
// .stream().map(this::getTestAction).collect(Collectors.toMap(LifecycleAction::getWriteableName, Function.identity()));
|
||||
// Phase deletePhase = new Phase("delete", TimeValue.ZERO, actions);
|
||||
//
|
||||
// MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, "", "",
|
||||
// 0, TEST_NOW_SUPPLIER) {
|
||||
//
|
||||
// @Override
|
||||
// public boolean canExecute(Phase phase) {
|
||||
// assertSame(deletePhase, phase);
|
||||
// return true;
|
||||
// }
|
||||
// };
|
||||
// TimeseriesLifecycleType policy = TimeseriesLifecycleType.INSTANCE;
|
||||
// LifecyclePolicy.NextActionProvider provider = policy.getActionProvider(context, deletePhase);
|
||||
// assertThat(provider.next(null), equalTo(TEST_DELETE_ACTION));
|
||||
// assertNull(provider.next(TEST_DELETE_ACTION));
|
||||
// }
|
||||
//
|
||||
//
|
||||
// private LifecycleAction getTestAction(String actionName) {
|
||||
// switch (actionName) {
|
||||
// case AllocateAction.NAME:
|
||||
// return TEST_ALLOCATE_ACTION;
|
||||
// case DeleteAction.NAME:
|
||||
// return TEST_DELETE_ACTION;
|
||||
// case ForceMergeAction.NAME:
|
||||
// return TEST_FORCE_MERGE_ACTION;
|
||||
// case ReplicasAction.NAME:
|
||||
// return TEST_REPLICAS_ACTION;
|
||||
// case RolloverAction.NAME:
|
||||
// return TEST_ROLLOVER_ACTION;
|
||||
// case ShrinkAction.NAME:
|
||||
// return TEST_SHRINK_ACTION;
|
||||
// default:
|
||||
// throw new IllegalArgumentException("unsupported timeseries phase action [" + actionName + "]");
|
||||
// }
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -105,7 +105,9 @@ public class IndexLifecycle extends Plugin implements ActionPlugin {
|
|||
LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE_SETTING,
|
||||
LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING,
|
||||
LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING,
|
||||
LifecycleSettings.LIFECYCLE_ACTION_SETTING);
|
||||
LifecycleSettings.LIFECYCLE_ACTION_SETTING,
|
||||
LifecycleSettings.LIFECYCLE_STEP_TIME_SETTING,
|
||||
LifecycleSettings.LIFECYCLE_STEP_SETTING);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -27,14 +27,18 @@ import org.elasticsearch.common.unit.TimeValue;
|
|||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Step;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.StepResult;
|
||||
import org.elasticsearch.xpack.core.scheduler.SchedulerEngine;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.time.Clock;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.SortedMap;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.LongSupplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A service which runs the {@link LifecyclePolicy}s associated with indexes.
|
||||
|
@ -112,38 +116,49 @@ public class IndexLifecycleService extends AbstractComponent
|
|||
scheduler.get().add(scheduledJob);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void triggered(SchedulerEngine.Event event) {
|
||||
if (event.getJobName().equals(IndexLifecycle.NAME)) {
|
||||
logger.info("Job triggered: " + event.getJobName() + ", " + event.getScheduledTime() + ", " + event.getTriggeredTime());
|
||||
public synchronized void triggerPolicies() {
|
||||
IndexLifecycleMetadata indexLifecycleMetadata = clusterService.state().metaData().custom(IndexLifecycleMetadata.TYPE);
|
||||
SortedMap<String, LifecyclePolicy> policies = indexLifecycleMetadata.getPolicies();
|
||||
// loop through all indices in cluster state and filter for ones that are
|
||||
// managed by the Index Lifecycle Service they have a index.lifecycle.name setting
|
||||
// associated to a policy
|
||||
clusterService.state().metaData().indices().valuesIt().forEachRemaining((idxMeta) -> {
|
||||
ClusterState clusterState = clusterService.state();
|
||||
clusterState.metaData().indices().valuesIt().forEachRemaining((idxMeta) -> {
|
||||
String policyName = LifecycleSettings.LIFECYCLE_NAME_SETTING.get(idxMeta.getSettings());
|
||||
if (Strings.isNullOrEmpty(policyName) == false) {
|
||||
// ensure that all managed indices have `index.lifecycle.date` set
|
||||
// and then execute their respective lifecycle policies.
|
||||
putLifecycleDate(idxMeta).thenRun(() -> executePolicy(idxMeta, policies, policyName));
|
||||
LifecyclePolicy policy = policies.get(policyName);
|
||||
// fetch step
|
||||
// check whether complete
|
||||
// if complete, launch next task
|
||||
clusterService.submitStateUpdateTask("index-lifecycle-" + policyName, new ClusterStateUpdateTask() {
|
||||
@Override
|
||||
public ClusterState execute(ClusterState currentState) throws Exception {
|
||||
// ensure date is set
|
||||
currentState = putLifecycleDate(currentState, idxMeta);
|
||||
long lifecycleDate = currentState.metaData().settings()
|
||||
.getAsLong(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, -1L);
|
||||
// TODO(talevy): make real
|
||||
List<Step> steps = policy.getPhases().values().stream()
|
||||
.flatMap(p -> p.toSteps(idxMeta.getIndex(), lifecycleDate, client, threadPool, nowSupplier).stream())
|
||||
.collect(Collectors.toList());
|
||||
StepResult result = policy.execute(steps, currentState, idxMeta, client, nowSupplier);
|
||||
return result.getClusterState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(String source, Exception e) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void executePolicy(IndexMetaData idxMeta, SortedMap<String, LifecyclePolicy> policies, String policyName) {
|
||||
logger.info("Checking index for next action: " + idxMeta.getIndex().getName() + " (" + policyName + ")");
|
||||
LifecyclePolicy policy = policies.get(policyName);
|
||||
if (policy == null) {
|
||||
logger.error("Unknown lifecycle policy [{}] for index [{}]", policyName, idxMeta.getIndex().getName());
|
||||
} else {
|
||||
try {
|
||||
policy.execute(new InternalIndexLifecycleContext(idxMeta.getIndex(), client, clusterService, nowSupplier));
|
||||
} catch (Exception e) {
|
||||
logger.error(new FormattedMessage("Failed to execute lifecycle policy [{}] for index [{}]", policyName,
|
||||
idxMeta.getIndex().getName()), e);
|
||||
}
|
||||
@Override
|
||||
public void triggered(SchedulerEngine.Event event) {
|
||||
if (event.getJobName().equals(IndexLifecycle.NAME)) {
|
||||
logger.info("Job triggered: " + event.getJobName() + ", " + event.getScheduledTime() + ", " + event.getTriggeredTime());
|
||||
triggerPolicies();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -166,29 +181,17 @@ public class IndexLifecycleService extends AbstractComponent
|
|||
}));
|
||||
}
|
||||
|
||||
private CompletableFuture<Void> putLifecycleDate(IndexMetaData idxMeta) {
|
||||
CompletableFuture<Void> completableFuture = new CompletableFuture<>();
|
||||
if (idxMeta.getSettings().hasValue(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE_SETTING.getKey())) {
|
||||
completableFuture.complete(null);
|
||||
private ClusterState putLifecycleDate(ClusterState clusterState, IndexMetaData idxMeta) {
|
||||
if (idxMeta.getSettings().hasValue(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE)) {
|
||||
return clusterState;
|
||||
} else {
|
||||
UpdateSettingsRequest updateSettingsRequest = new UpdateSettingsRequest(Settings.builder()
|
||||
.put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE_SETTING.getKey(), idxMeta.getCreationDate()).build(),
|
||||
idxMeta.getIndex().getName());
|
||||
client.admin().indices().updateSettings(updateSettingsRequest, new ActionListener<UpdateSettingsResponse>() {
|
||||
@Override
|
||||
public void onResponse(UpdateSettingsResponse updateSettingsResponse) {
|
||||
completableFuture.complete(null);
|
||||
ClusterState.Builder builder = new ClusterState.Builder(clusterState);
|
||||
MetaData.Builder metadataBuilder = MetaData.builder(clusterState.metaData());
|
||||
Settings settings = Settings.builder()
|
||||
.put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE_SETTING.getKey(), idxMeta.getCreationDate()).build();
|
||||
metadataBuilder.updateSettings(settings, idxMeta.getIndex().getName());
|
||||
return builder.metaData(metadataBuilder.build()).build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
logger.error("unable to update " + LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE + " setting on indices", e);
|
||||
completableFuture.completeExceptionally(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return completableFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* 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.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleContext;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Phase;
|
||||
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
/**
|
||||
* An Implementation of {@link IndexLifecycleContext} which writes lifecycle
|
||||
* state to index settings.
|
||||
*/
|
||||
public class InternalIndexLifecycleContext implements IndexLifecycleContext {
|
||||
|
||||
private Client client;
|
||||
private Index index;
|
||||
private LongSupplier nowSupplier;
|
||||
private ClusterService clusterService;
|
||||
|
||||
/**
|
||||
* @param index
|
||||
* the {@link Index} for this context.
|
||||
* @param client
|
||||
* the {@link Client} to use when modifying the index settings.
|
||||
* @param nowSupplier
|
||||
* a {@link LongSupplier} to provide the current timestamp when
|
||||
* required.
|
||||
*/
|
||||
public InternalIndexLifecycleContext(Index index, Client client, ClusterService clusterService, LongSupplier nowSupplier) {
|
||||
this.index = index;
|
||||
this.client = client;
|
||||
this.clusterService = clusterService;
|
||||
this.nowSupplier = nowSupplier;
|
||||
}
|
||||
|
||||
private IndexMetaData getIdxMetaData() {
|
||||
return clusterService.state().metaData().index(index.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPhase(String phase, Listener listener) {
|
||||
Settings newLifecyclePhaseSettings = Settings.builder()
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE, phase)
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE_TIME, nowSupplier.getAsLong())
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, -1L)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, "").build();
|
||||
writeSettings(index.getName(), newLifecyclePhaseSettings, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPhase() {
|
||||
return LifecycleSettings.LIFECYCLE_PHASE_SETTING.get(getIdxMetaData().getSettings());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPhaseTime() {
|
||||
return LifecycleSettings.LIFECYCLE_PHASE_TIME_SETTING.get(getIdxMetaData().getSettings());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setAction(String action, Listener listener) {
|
||||
Settings newLifecycleActionSettings = Settings.builder()
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, action)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, nowSupplier.getAsLong())
|
||||
.build();
|
||||
writeSettings(index.getName(), newLifecycleActionSettings, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAction() {
|
||||
return LifecycleSettings.LIFECYCLE_ACTION_SETTING.get(getIdxMetaData().getSettings());
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getActionTime() {
|
||||
return LifecycleSettings.LIFECYCLE_ACTION_TIME_SETTING.get(getIdxMetaData().getSettings());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLifecycleTarget() {
|
||||
return index.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfReplicas() {
|
||||
return getIdxMetaData().getNumberOfReplicas();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
long now = nowSupplier.getAsLong();
|
||||
long initialIndexCreated = LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE_SETTING.get(getIdxMetaData().getSettings());
|
||||
return (initialIndexCreated + phase.getAfter().millis()) <= now;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void executeAction(LifecycleAction action, LifecycleAction.Listener listener) {
|
||||
action.execute(index, client, clusterService, listener);
|
||||
}
|
||||
|
||||
private void writeSettings(String index, Settings settings, Listener listener) {
|
||||
client.admin().indices().updateSettings(new UpdateSettingsRequest(settings, index), new ActionListener<UpdateSettingsResponse>() {
|
||||
|
||||
@Override
|
||||
public void onResponse(UpdateSettingsResponse response) {
|
||||
if (response.isAcknowledged()) {
|
||||
listener.onSuccess();
|
||||
} else {
|
||||
listener.onFailure(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
listener.onFailure(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
|
||||
public class ClusterStateUpdateStepTests extends ESTestCase {
|
||||
|
||||
public void test() {
|
||||
|
||||
}
|
||||
}
|
|
@ -278,7 +278,7 @@ public class IndexLifecycleServiceTests extends ESTestCase {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void testTriggeredWithMatchingPolicy() {
|
||||
String policyName = randomAlphaOfLengthBetween(1, 20);
|
||||
MockAction mockAction = new MockAction();
|
||||
MockAction mockAction = new MockAction(Collections.emptyList());
|
||||
Phase phase = new Phase("phase", TimeValue.ZERO, Collections.singletonMap("action", mockAction));
|
||||
LifecyclePolicy policy = new LifecyclePolicy(TestLifecycleType.INSTANCE, policyName,
|
||||
Collections.singletonMap(phase.getName(), phase));
|
||||
|
@ -352,7 +352,7 @@ public class IndexLifecycleServiceTests extends ESTestCase {
|
|||
@SuppressWarnings("unchecked")
|
||||
public void testTriggeredWithDateSettingAlreadyPresent() {
|
||||
String policyName = randomAlphaOfLengthBetween(1, 20);
|
||||
MockAction mockAction = new MockAction();
|
||||
MockAction mockAction = new MockAction(Collections.emptyList());
|
||||
Phase phase = new Phase("phase", TimeValue.ZERO, Collections.singletonMap("action", mockAction));
|
||||
LifecyclePolicy policy = new LifecyclePolicy(TestLifecycleType.INSTANCE, policyName,
|
||||
Collections.singletonMap(phase.getName(), phase));
|
||||
|
@ -409,7 +409,7 @@ public class IndexLifecycleServiceTests extends ESTestCase {
|
|||
*/
|
||||
public void testTriggeredUnknownPolicyNameSet() {
|
||||
String policyName = randomAlphaOfLengthBetween(1, 20);
|
||||
MockAction mockAction = new MockAction();
|
||||
MockAction mockAction = new MockAction(Collections.emptyList());
|
||||
Phase phase = new Phase("phase", TimeValue.ZERO, Collections.singletonMap("action", mockAction));
|
||||
LifecyclePolicy policy = new LifecyclePolicy(TestLifecycleType.INSTANCE, policyName,
|
||||
Collections.singletonMap(phase.getName(), phase));
|
||||
|
@ -453,7 +453,7 @@ public class IndexLifecycleServiceTests extends ESTestCase {
|
|||
*/
|
||||
public void testTriggeredNoPolicyNameSet() {
|
||||
String policyName = randomAlphaOfLengthBetween(1, 20);
|
||||
MockAction mockAction = new MockAction();
|
||||
MockAction mockAction = new MockAction(Collections.emptyList());
|
||||
Phase phase = new Phase("phase", TimeValue.ZERO, Collections.singletonMap("action", mockAction));
|
||||
LifecyclePolicy policy = new LifecyclePolicy(TestLifecycleType.INSTANCE, policyName,
|
||||
Collections.singletonMap(phase.getName(), phase));
|
||||
|
|
|
@ -1,641 +0,0 @@
|
|||
/*
|
||||
* 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.indexlifecycle;
|
||||
|
||||
import org.apache.lucene.util.SetOnce;
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.action.ActionListener;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsRequest;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsResponse;
|
||||
import org.elasticsearch.action.admin.indices.settings.put.UpdateSettingsTestHelper;
|
||||
import org.elasticsearch.client.AdminClient;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.client.IndicesAdminClient;
|
||||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.collect.ImmutableOpenMap;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.test.ESTestCase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.IndexLifecycleContext.Listener;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.MockAction;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Phase;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.InvocationOnMock;
|
||||
import org.mockito.stubbing.Answer;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
public class InternalIndexLifecycleContextTests extends ESTestCase {
|
||||
private static final Index TEST_INDEX = new Index("test", "test");
|
||||
|
||||
private ClusterState getClusterState(IndexMetaData indexMetaData) {
|
||||
ImmutableOpenMap.Builder<String, IndexMetaData> indices = ImmutableOpenMap.<String, IndexMetaData> builder()
|
||||
.fPut(indexMetaData.getIndex().getName(), indexMetaData);
|
||||
MetaData metaData = MetaData.builder().indices(indices.build())
|
||||
.persistentSettings(settings(Version.CURRENT).build()).build();
|
||||
return ClusterState.builder(ClusterName.DEFAULT).metaData(metaData).build();
|
||||
}
|
||||
|
||||
public void testSetPhase() {
|
||||
long oldNow = randomNonNegativeLong();
|
||||
long now = randomNonNegativeLong();
|
||||
LongSupplier nowSupplier = () -> now;
|
||||
long creationDate = randomNonNegativeLong();
|
||||
String oldPhase = randomAlphaOfLengthBetween(1, 5);
|
||||
String newPhase = randomAlphaOfLengthBetween(6, 10);
|
||||
Settings expectedSettings = Settings.builder().put(LifecycleSettings.LIFECYCLE_PHASE, newPhase)
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE_TIME, now)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, -1L)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, "").build();
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).put("index.creation_date", creationDate)
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE, oldPhase)
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE_TIME, oldNow)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, oldNow)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, randomAlphaOfLengthBetween(1, 20)).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterState updatedClusterState = getClusterState(IndexMetaData.builder(idxMeta)
|
||||
.settings(Settings.builder().put(idxMeta.getSettings()).put(expectedSettings)).build());
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState, updatedClusterState);
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
|
||||
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
UpdateSettingsRequest request = (UpdateSettingsRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocation.getArguments()[1];
|
||||
UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, TEST_INDEX.getName());
|
||||
listener.onResponse(UpdateSettingsTestHelper.createMockResponse(true));
|
||||
return null;
|
||||
}
|
||||
}).when(indicesClient).updateSettings(Mockito.any(), Mockito.any());
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, client, clusterService, nowSupplier);
|
||||
|
||||
// Use setOnce so it throws an error if we call the listener multiple
|
||||
// times
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
assertEquals(oldPhase, context.getPhase());
|
||||
context.setPhase(newPhase, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected Error", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, listenerCalled.get());
|
||||
assertEquals(newPhase, context.getPhase());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).updateSettings(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testSetPhaseNotAcknowledged() {
|
||||
long now = randomNonNegativeLong();
|
||||
LongSupplier nowSupplier = () -> now;
|
||||
long creationDate = randomNonNegativeLong();
|
||||
String newPhase = randomAlphaOfLengthBetween(1, 20);
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).put("index.creation_date", creationDate)
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE, randomAlphaOfLengthBetween(1, 20))
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE_TIME, now)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, randomAlphaOfLengthBetween(1, 20)).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
UpdateSettingsRequest request = (UpdateSettingsRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocation.getArguments()[1];
|
||||
Settings expectedSettings = Settings.builder().put(LifecycleSettings.LIFECYCLE_PHASE, newPhase)
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE_TIME, now)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, -1L)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, "").build();
|
||||
UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, TEST_INDEX.getName());
|
||||
listener.onResponse(UpdateSettingsTestHelper.createMockResponse(false));
|
||||
return null;
|
||||
}
|
||||
}).when(indicesClient).updateSettings(Mockito.any(), Mockito.any());
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, client, clusterService, nowSupplier);
|
||||
|
||||
// Use setOnce so it throws an error if we call the listener multiple
|
||||
// times
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
context.setPhase(newPhase, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
throw new AssertionError("Unexpected Error");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
assertNull(e);
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, listenerCalled.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).updateSettings(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testSetPhaseFailure() {
|
||||
long now = randomNonNegativeLong();
|
||||
LongSupplier nowSupplier = () -> now;
|
||||
long creationDate = randomNonNegativeLong();
|
||||
String newPhase = randomAlphaOfLengthBetween(1, 20);
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).put("index.creation_date", creationDate)
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE, randomAlphaOfLengthBetween(1, 20))
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE_TIME, now)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, randomAlphaOfLengthBetween(1, 20)).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
Exception exception = new RuntimeException();
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
UpdateSettingsRequest request = (UpdateSettingsRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocation.getArguments()[1];
|
||||
Settings expectedSettings = Settings.builder().put(LifecycleSettings.LIFECYCLE_PHASE, newPhase)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, -1L).put(LifecycleSettings.LIFECYCLE_PHASE_TIME, now)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, "").build();
|
||||
UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, TEST_INDEX.getName());
|
||||
listener.onFailure(exception);
|
||||
return null;
|
||||
}
|
||||
}).when(indicesClient).updateSettings(Mockito.any(), Mockito.any());
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, client, clusterService, nowSupplier);
|
||||
|
||||
// Use setOnce so it throws an error if we call the listener multiple
|
||||
// times
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
context.setPhase(newPhase, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
throw new AssertionError("Unexpected Error");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
assertSame(exception, e);
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, listenerCalled.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).updateSettings(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testGetPhase() {
|
||||
long creationDate = randomNonNegativeLong();
|
||||
String phase = randomAlphaOfLengthBetween(1, 20);
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).put("index.creation_date", creationDate)
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE, phase).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, null, clusterService, () -> {
|
||||
throw new AssertionError("nowSupplier should not be called");
|
||||
});
|
||||
|
||||
assertEquals(phase, context.getPhase());
|
||||
}
|
||||
|
||||
public void testGetPhaseTime() {
|
||||
long creationDate = randomNonNegativeLong();
|
||||
long phaseTime = randomNonNegativeLong();
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).put("index.creation_date", creationDate)
|
||||
.put(LifecycleSettings.LIFECYCLE_PHASE_TIME, phaseTime).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, null, clusterService, () -> {
|
||||
throw new AssertionError("nowSupplier should not be called");
|
||||
});
|
||||
|
||||
assertEquals(phaseTime, context.getPhaseTime());
|
||||
}
|
||||
|
||||
public void testGetReplicas() {
|
||||
int replicas = randomIntBetween(0, 5);
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(replicas).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, null, clusterService, () -> {
|
||||
throw new AssertionError("nowSupplier should not be called");
|
||||
});
|
||||
|
||||
assertEquals(replicas, context.getNumberOfReplicas());
|
||||
}
|
||||
|
||||
public void testSetAction() {
|
||||
long now = randomNonNegativeLong();
|
||||
LongSupplier nowSupplier = () -> now;
|
||||
long creationDate = randomNonNegativeLong();
|
||||
String oldAction = randomAlphaOfLengthBetween(1, 5);
|
||||
String newAction = randomAlphaOfLengthBetween(6, 10);
|
||||
Settings expectedSettings = Settings.builder().put(LifecycleSettings.LIFECYCLE_ACTION, newAction)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, now).build();
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).put("index.creation_date", creationDate)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, now).put(LifecycleSettings.LIFECYCLE_ACTION, oldAction).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterState updatedClusterState = getClusterState(IndexMetaData.builder(idxMeta)
|
||||
.settings(Settings.builder().put(idxMeta.getSettings()).put(expectedSettings)).build());
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState, updatedClusterState);
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
UpdateSettingsRequest request = (UpdateSettingsRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocation.getArguments()[1];
|
||||
UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, TEST_INDEX.getName());
|
||||
listener.onResponse(UpdateSettingsTestHelper.createMockResponse(true));
|
||||
return null;
|
||||
}
|
||||
}).when(indicesClient).updateSettings(Mockito.any(), Mockito.any());
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, client, clusterService, nowSupplier);
|
||||
|
||||
// Use setOnce so it throws an error if we call the listener multiple
|
||||
// times
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
assertEquals(oldAction, context.getAction());
|
||||
context.setAction(newAction, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected Error", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, listenerCalled.get());
|
||||
assertEquals(newAction, context.getAction());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).updateSettings(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testSetActionNotAcknowledged() {
|
||||
long now = randomNonNegativeLong();
|
||||
LongSupplier nowSupplier = () -> now;
|
||||
long creationDate = randomNonNegativeLong();
|
||||
String newAction = randomAlphaOfLengthBetween(1, 20);
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).put("index.creation_date", creationDate)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, now)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, randomAlphaOfLengthBetween(1, 20)).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
UpdateSettingsRequest request = (UpdateSettingsRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocation.getArguments()[1];
|
||||
Settings expectedSettings = Settings.builder().put(LifecycleSettings.LIFECYCLE_ACTION, newAction)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, now).build();
|
||||
UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, TEST_INDEX.getName());
|
||||
listener.onResponse(UpdateSettingsTestHelper.createMockResponse(false));
|
||||
return null;
|
||||
}
|
||||
}).when(indicesClient).updateSettings(Mockito.any(), Mockito.any());
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, client, clusterService, nowSupplier);
|
||||
|
||||
// Use setOnce so it throws an error if we call the listener multiple
|
||||
// times
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
context.setAction(newAction, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
throw new AssertionError("Unexpected Error");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
assertNull(e);
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, listenerCalled.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).updateSettings(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testSetActionFailure() {
|
||||
long now = randomNonNegativeLong();
|
||||
LongSupplier nowSupplier = () -> now;
|
||||
long creationDate = randomNonNegativeLong();
|
||||
String newAction = randomAlphaOfLengthBetween(1, 20);
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).put("index.creation_date", creationDate)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, now)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, randomAlphaOfLengthBetween(1, 20)).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
Exception exception = new RuntimeException();
|
||||
|
||||
Client client = Mockito.mock(Client.class);
|
||||
AdminClient adminClient = Mockito.mock(AdminClient.class);
|
||||
IndicesAdminClient indicesClient = Mockito.mock(IndicesAdminClient.class);
|
||||
|
||||
Mockito.when(client.admin()).thenReturn(adminClient);
|
||||
Mockito.when(adminClient.indices()).thenReturn(indicesClient);
|
||||
Mockito.doAnswer(new Answer<Void>() {
|
||||
|
||||
@Override
|
||||
public Void answer(InvocationOnMock invocation) throws Throwable {
|
||||
UpdateSettingsRequest request = (UpdateSettingsRequest) invocation.getArguments()[0];
|
||||
@SuppressWarnings("unchecked")
|
||||
ActionListener<UpdateSettingsResponse> listener = (ActionListener<UpdateSettingsResponse>) invocation.getArguments()[1];
|
||||
Settings expectedSettings = Settings.builder().put(LifecycleSettings.LIFECYCLE_ACTION, newAction)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, now).build();
|
||||
UpdateSettingsTestHelper.assertSettingsRequest(request, expectedSettings, TEST_INDEX.getName());
|
||||
listener.onFailure(exception);
|
||||
return null;
|
||||
}
|
||||
}).when(indicesClient).updateSettings(Mockito.any(), Mockito.any());
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, client, clusterService, nowSupplier);
|
||||
|
||||
// Use setOnce so it throws an error if we call the listener multiple
|
||||
// times
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
context.setAction(newAction, new Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
throw new AssertionError("Unexpected Error");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
assertSame(exception, e);
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
});
|
||||
|
||||
assertEquals(true, listenerCalled.get());
|
||||
|
||||
Mockito.verify(client, Mockito.only()).admin();
|
||||
Mockito.verify(adminClient, Mockito.only()).indices();
|
||||
Mockito.verify(indicesClient, Mockito.only()).updateSettings(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
public void testGetAction() {
|
||||
long creationDate = randomNonNegativeLong();
|
||||
String action = randomAlphaOfLengthBetween(1, 20);
|
||||
IndexMetaData idxMeta = IndexMetaData.builder("test")
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).put("index.creation_date", creationDate)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION, action).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, null, clusterService, () -> {
|
||||
throw new AssertionError("nowSupplier should not be called");
|
||||
});
|
||||
|
||||
assertEquals(action, context.getAction());
|
||||
}
|
||||
|
||||
public void testGetActionTime() {
|
||||
long creationDate = randomNonNegativeLong();
|
||||
long actionTime = randomNonNegativeLong();
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).put("index.creation_date", creationDate)
|
||||
.put(LifecycleSettings.LIFECYCLE_ACTION_TIME, actionTime).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, null, clusterService, () -> {
|
||||
throw new AssertionError("nowSupplier should not be called");
|
||||
});
|
||||
|
||||
assertEquals(actionTime, context.getActionTime());
|
||||
}
|
||||
|
||||
public void testGetLifecycleTarget() {
|
||||
long creationDate = randomNonNegativeLong();
|
||||
Index index = new Index(randomAlphaOfLengthBetween(1, 20), randomAlphaOfLengthBetween(1, 20));
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(index.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).put("index.creation_date", creationDate).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(index, null, clusterService, () -> {
|
||||
throw new AssertionError("nowSupplier should not be called");
|
||||
});
|
||||
|
||||
assertEquals(index.getName(), context.getLifecycleTarget());
|
||||
}
|
||||
|
||||
public void testCanExecuteBeforeTrigger() {
|
||||
TimeValue after = TimeValue.timeValueSeconds(randomIntBetween(0, 100000));
|
||||
long creationDate = randomNonNegativeLong();
|
||||
long now = random().longs(creationDate, creationDate + after.millis()).iterator().nextLong();
|
||||
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L)
|
||||
.put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, creationDate).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, null, clusterService, () -> now);
|
||||
|
||||
Phase phase = new Phase("test_phase", after, Collections.emptyMap());
|
||||
|
||||
assertFalse(context.canExecute(phase));
|
||||
}
|
||||
|
||||
public void testCanExecuteOnTrigger() {
|
||||
TimeValue after = TimeValue.timeValueSeconds(randomIntBetween(0, 100000));
|
||||
long creationDate = randomNonNegativeLong();
|
||||
long now = creationDate + after.millis();
|
||||
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L)
|
||||
.put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, creationDate).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, null, clusterService, () -> now);
|
||||
|
||||
Phase phase = new Phase("test_phase", after, Collections.emptyMap());
|
||||
|
||||
assertTrue(context.canExecute(phase));
|
||||
}
|
||||
|
||||
public void testCanExecuteAfterTrigger() {
|
||||
TimeValue after = TimeValue.timeValueSeconds(randomIntBetween(0, 100000));
|
||||
long creationDate = randomNonNegativeLong();
|
||||
long now = random().longs(creationDate + after.millis(), Long.MAX_VALUE).iterator().nextLong();
|
||||
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L)
|
||||
.put(LifecycleSettings.LIFECYCLE_INDEX_CREATION_DATE, creationDate).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, null, clusterService, () -> now);
|
||||
|
||||
Phase phase = new Phase("test_phase", after, Collections.emptyMap());
|
||||
|
||||
assertTrue(context.canExecute(phase));
|
||||
}
|
||||
|
||||
public void testExecuteAction() {
|
||||
IndexMetaData idxMeta = IndexMetaData.builder(TEST_INDEX.getName())
|
||||
.settings(Settings.builder().put("index.version.created", 7000001L).put("index.creation_date", 0L).build())
|
||||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
ClusterState clusterState = getClusterState(idxMeta);
|
||||
ClusterService clusterService = Mockito.mock(ClusterService.class);
|
||||
Mockito.when(clusterService.state()).thenReturn(clusterState);
|
||||
|
||||
InternalIndexLifecycleContext context = new InternalIndexLifecycleContext(TEST_INDEX, null, clusterService, () -> {
|
||||
throw new AssertionError("nowSupplier should not be called");
|
||||
});
|
||||
|
||||
MockAction action = new MockAction();
|
||||
action.setCompleteOnExecute(true);
|
||||
|
||||
assertFalse(action.wasCompleted());
|
||||
assertEquals(0L, action.getExecutedCount());
|
||||
|
||||
SetOnce<Boolean> listenerCalled = new SetOnce<>();
|
||||
|
||||
context.executeAction(action, new LifecycleAction.Listener() {
|
||||
|
||||
@Override
|
||||
public void onSuccess(boolean completed) {
|
||||
listenerCalled.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
throw new AssertionError("Unexpected method call", e);
|
||||
}
|
||||
});
|
||||
|
||||
assertTrue(action.wasCompleted());
|
||||
assertEquals(1L, action.getExecutedCount());
|
||||
assertEquals(true, listenerCalled.get());
|
||||
}
|
||||
}
|
|
@ -5,24 +5,35 @@
|
|||
*/
|
||||
package org.elasticsearch.xpack.indexlifecycle;
|
||||
|
||||
import org.elasticsearch.Version;
|
||||
import org.elasticsearch.client.Client;
|
||||
import org.elasticsearch.cluster.ClusterModule;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.cluster.metadata.MetaData;
|
||||
import org.elasticsearch.common.ParseField;
|
||||
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
|
||||
import org.elasticsearch.common.io.stream.Writeable.Reader;
|
||||
import org.elasticsearch.common.unit.TimeValue;
|
||||
import org.elasticsearch.common.xcontent.NamedXContentRegistry;
|
||||
import org.elasticsearch.common.xcontent.XContentParser;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.test.AbstractSerializingTestCase;
|
||||
import org.elasticsearch.threadpool.TestThreadPool;
|
||||
import org.elasticsearch.threadpool.ThreadPool;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.ClusterStateUpdateStep;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.ConditionalWaitStep;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.DeleteAction;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleAction;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecyclePolicy;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleType;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.MockAction;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.MockIndexLifecycleContext;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Phase;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.PhaseAfterStep;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Step;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.StepResult;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.TimeseriesLifecycleType;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.TestLifecycleType;
|
||||
import org.junit.Before;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
|
@ -32,6 +43,9 @@ import java.util.HashMap;
|
|||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
import static org.mockito.Mockito.mock;
|
||||
|
||||
public class LifecyclePolicyTests extends AbstractSerializingTestCase<LifecyclePolicy> {
|
||||
|
||||
|
@ -112,347 +126,36 @@ public class LifecyclePolicyTests extends AbstractSerializingTestCase<LifecycleP
|
|||
assertSame(TimeseriesLifecycleType.INSTANCE, policy.getType());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void setupPolicy() {
|
||||
public void testSteps() throws Exception {
|
||||
ThreadPool threadPool = new TestThreadPool("test");
|
||||
LongSupplier nowSupplier = () -> 0L;
|
||||
Client client = mock(Client.class);
|
||||
Step phaseAfterStep = new PhaseAfterStep(threadPool, 0L, nowSupplier,
|
||||
TimeValue.timeValueSeconds(0L), "name-0", "index", "phase", "mock_action");
|
||||
Step updateStep = new ClusterStateUpdateStep("name-1", "index", "phase", "mock_action",
|
||||
(state) -> state);
|
||||
Step waitStep = new ConditionalWaitStep("name-2", "index", "phase", "mock_action",
|
||||
(state) -> true);
|
||||
indexName = randomAlphaOfLengthBetween(1, 20);
|
||||
lifecycleName = randomAlphaOfLengthBetween(1, 20);
|
||||
Map<String, Phase> phases = new LinkedHashMap<>();
|
||||
firstAction = new MockAction();
|
||||
firstAction = new MockAction(Arrays.asList(phaseAfterStep, updateStep, waitStep));
|
||||
Map<String, LifecycleAction> actions = Collections.singletonMap(MockAction.NAME, firstAction);
|
||||
TimeValue after = TimeValue.timeValueSeconds(0);
|
||||
firstPhase = new Phase("first_phase", after, actions);
|
||||
firstPhase = new Phase("phase", null, actions);
|
||||
phases.put(firstPhase.getName(), firstPhase);
|
||||
secondAction = new MockAction();
|
||||
actions = Collections.singletonMap(MockAction.NAME, secondAction);
|
||||
after = TimeValue.timeValueSeconds(10);
|
||||
secondPhase = new Phase("second_phase", after, actions);
|
||||
phases.put(secondPhase.getName(), secondPhase);
|
||||
thirdAction = new MockAction();
|
||||
actions = Collections.singletonMap(MockAction.NAME, thirdAction);
|
||||
after = TimeValue.timeValueSeconds(20);
|
||||
thirdPhase = new Phase("third_phase", after, actions);
|
||||
phases.put(thirdPhase.getName(), thirdPhase);
|
||||
policy = new LifecyclePolicy(TestLifecycleType.INSTANCE, lifecycleName, phases);
|
||||
}
|
||||
policy = new LifecyclePolicy(TestLifecycleType.INSTANCE, lifecycleName, null);
|
||||
|
||||
public void testExecuteNewIndexBeforeTrigger() throws Exception {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, "", "", 0, () -> 0L) {
|
||||
List<Step> phaseSteps = firstPhase.toSteps(new Index(indexName, indexName), 0L,
|
||||
client, threadPool, nowSupplier);
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
if (phase == firstPhase) {
|
||||
return false;
|
||||
} else {
|
||||
throw new AssertionError("canExecute should not have been called on this phase: " + phase.getName());
|
||||
ClusterState clusterState = ClusterState.builder(ClusterState.EMPTY_STATE)
|
||||
.metaData(MetaData.builder().put(
|
||||
IndexMetaData.builder("index")
|
||||
.settings(settings(Version.CURRENT))
|
||||
.numberOfShards(1).numberOfReplicas(1))).build();
|
||||
|
||||
StepResult result = policy.execute(phaseSteps, clusterState, clusterState.metaData().index("index"), client, nowSupplier);
|
||||
|
||||
threadPool.shutdown();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
policy.execute(context);
|
||||
|
||||
assertEquals(indexName, context.getLifecycleTarget());
|
||||
assertEquals("", context.getPhase());
|
||||
assertEquals("", context.getAction());
|
||||
|
||||
assertFalse(firstAction.wasCompleted());
|
||||
assertEquals(0L, firstAction.getExecutedCount());
|
||||
assertFalse(secondAction.wasCompleted());
|
||||
assertEquals(0L, secondAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(0L, thirdAction.getExecutedCount());
|
||||
}
|
||||
|
||||
public void testExecuteNewIndexAfterTrigger() throws Exception {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, "", "", 0, () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
if (phase == firstPhase) {
|
||||
return true;
|
||||
} else {
|
||||
throw new AssertionError("canExecute should not have been called on this phase: " + phase.getName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
policy.execute(context);
|
||||
|
||||
assertEquals(indexName, context.getLifecycleTarget());
|
||||
assertEquals(firstPhase.getName(), context.getPhase());
|
||||
assertEquals(MockAction.NAME, context.getAction());
|
||||
|
||||
assertFalse(firstAction.wasCompleted());
|
||||
assertEquals(1L, firstAction.getExecutedCount());
|
||||
assertFalse(secondAction.wasCompleted());
|
||||
assertEquals(0L, secondAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(0L, thirdAction.getExecutedCount());
|
||||
}
|
||||
|
||||
public void testExecuteNewIndexAfterTriggerFailure() throws Exception {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, "", "", 0, () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
if (phase == firstPhase) {
|
||||
return true;
|
||||
} else {
|
||||
throw new AssertionError("canExecute should not have been called on this phase: " + phase.getName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
RuntimeException exception = new RuntimeException();
|
||||
|
||||
context.failOnSetters(exception);
|
||||
|
||||
policy.execute(context);
|
||||
|
||||
assertEquals(indexName, context.getLifecycleTarget());
|
||||
assertEquals("", context.getPhase());
|
||||
assertEquals("", context.getAction());
|
||||
|
||||
assertFalse(firstAction.wasCompleted());
|
||||
assertEquals(0L, firstAction.getExecutedCount());
|
||||
assertFalse(secondAction.wasCompleted());
|
||||
assertEquals(0L, secondAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(0L, thirdAction.getExecutedCount());
|
||||
}
|
||||
|
||||
public void testExecuteFirstPhase() throws Exception {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, firstPhase.getName(), "", 0, () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
|
||||
policy.execute(context);
|
||||
|
||||
assertEquals(indexName, context.getLifecycleTarget());
|
||||
assertEquals(firstPhase.getName(), context.getPhase());
|
||||
assertEquals(MockAction.NAME, context.getAction());
|
||||
|
||||
assertFalse(firstAction.wasCompleted());
|
||||
assertEquals(1L, firstAction.getExecutedCount());
|
||||
assertFalse(secondAction.wasCompleted());
|
||||
assertEquals(0L, secondAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(0L, thirdAction.getExecutedCount());
|
||||
}
|
||||
|
||||
public void testExecuteSecondPhase() throws Exception {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, secondPhase.getName(), "", 0, () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
|
||||
policy.execute(context);
|
||||
|
||||
assertEquals(indexName, context.getLifecycleTarget());
|
||||
assertEquals(secondPhase.getName(), context.getPhase());
|
||||
assertEquals(MockAction.NAME, context.getAction());
|
||||
|
||||
assertFalse(firstAction.wasCompleted());
|
||||
assertEquals(0L, firstAction.getExecutedCount());
|
||||
assertFalse(secondAction.wasCompleted());
|
||||
assertEquals(1L, secondAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(0L, thirdAction.getExecutedCount());
|
||||
}
|
||||
|
||||
public void testExecuteThirdPhase() throws Exception {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, thirdPhase.getName(), "", 0, () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
|
||||
policy.execute(context);
|
||||
|
||||
assertEquals(indexName, context.getLifecycleTarget());
|
||||
assertEquals(thirdPhase.getName(), context.getPhase());
|
||||
assertEquals(MockAction.NAME, context.getAction());
|
||||
|
||||
assertFalse(firstAction.wasCompleted());
|
||||
assertEquals(0L, firstAction.getExecutedCount());
|
||||
assertFalse(secondAction.wasCompleted());
|
||||
assertEquals(0L, secondAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(1L, thirdAction.getExecutedCount());
|
||||
}
|
||||
|
||||
public void testExecuteMissingPhase() throws Exception {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, "does_not_exist", "", 0, () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called.");
|
||||
}
|
||||
};
|
||||
|
||||
IllegalStateException exception = expectThrows(IllegalStateException.class, () -> policy.execute(context));
|
||||
assertEquals(
|
||||
"Current phase [" + "does_not_exist" + "] not found in lifecycle [" + lifecycleName + "] for index [" + indexName + "]",
|
||||
exception.getMessage());
|
||||
|
||||
assertEquals(indexName, context.getLifecycleTarget());
|
||||
assertEquals("does_not_exist", context.getPhase());
|
||||
assertEquals("", context.getAction());
|
||||
|
||||
assertFalse(firstAction.wasCompleted());
|
||||
assertEquals(0L, firstAction.getExecutedCount());
|
||||
assertFalse(secondAction.wasCompleted());
|
||||
assertEquals(0L, secondAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(0L, thirdAction.getExecutedCount());
|
||||
}
|
||||
|
||||
public void testExecuteFirstPhaseCompletedBeforeTrigger() throws Exception {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, firstPhase.getName(), Phase.PHASE_COMPLETED,
|
||||
0, () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
if (phase == secondPhase) {
|
||||
return false;
|
||||
} else {
|
||||
throw new AssertionError("canExecute should not have been called on this phase: " + phase.getName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
policy.execute(context);
|
||||
|
||||
assertEquals(indexName, context.getLifecycleTarget());
|
||||
assertEquals(firstPhase.getName(), context.getPhase());
|
||||
assertEquals(Phase.PHASE_COMPLETED, context.getAction());
|
||||
|
||||
assertFalse(firstAction.wasCompleted());
|
||||
assertEquals(0L, thirdAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(0L, secondAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(0L, thirdAction.getExecutedCount());
|
||||
}
|
||||
|
||||
public void testExecuteFirstPhaseCompletedAfterTrigger() throws Exception {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, firstPhase.getName(), Phase.PHASE_COMPLETED,
|
||||
0, () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
if (phase == secondPhase) {
|
||||
return true;
|
||||
} else {
|
||||
throw new AssertionError("canExecute should not have been called on this phase: " + phase.getName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
policy.execute(context);
|
||||
|
||||
assertEquals(indexName, context.getLifecycleTarget());
|
||||
assertEquals(secondPhase.getName(), context.getPhase());
|
||||
assertEquals(MockAction.NAME, context.getAction());
|
||||
|
||||
assertFalse(firstAction.wasCompleted());
|
||||
assertEquals(0L, firstAction.getExecutedCount());
|
||||
assertFalse(secondAction.wasCompleted());
|
||||
assertEquals(1L, secondAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(0L, thirdAction.getExecutedCount());
|
||||
}
|
||||
|
||||
public void testExecuteSecondPhaseCompletedBeforeTrigger() throws Exception {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, secondPhase.getName(), Phase.PHASE_COMPLETED,
|
||||
0, () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
if (phase == thirdPhase) {
|
||||
return false;
|
||||
} else {
|
||||
throw new AssertionError("canExecute should not have been called on this phase: " + phase.getName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
policy.execute(context);
|
||||
|
||||
assertEquals(indexName, context.getLifecycleTarget());
|
||||
assertEquals(secondPhase.getName(), context.getPhase());
|
||||
assertEquals(Phase.PHASE_COMPLETED, context.getAction());
|
||||
|
||||
assertFalse(firstAction.wasCompleted());
|
||||
assertEquals(0L, firstAction.getExecutedCount());
|
||||
assertFalse(secondAction.wasCompleted());
|
||||
assertEquals(0L, secondAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(0L, thirdAction.getExecutedCount());
|
||||
}
|
||||
|
||||
public void testExecuteSecondPhaseCompletedAfterTrigger() throws Exception {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, secondPhase.getName(), Phase.PHASE_COMPLETED,
|
||||
0, () -> 0L) {
|
||||
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
if (phase == thirdPhase) {
|
||||
return true;
|
||||
} else {
|
||||
throw new AssertionError("canExecute should not have been called on this phase: " + phase.getName());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
policy.execute(context);
|
||||
|
||||
assertEquals(indexName, context.getLifecycleTarget());
|
||||
assertEquals(thirdPhase.getName(), context.getPhase());
|
||||
assertEquals(MockAction.NAME, context.getAction());
|
||||
|
||||
assertFalse(firstAction.wasCompleted());
|
||||
assertEquals(0L, firstAction.getExecutedCount());
|
||||
assertFalse(secondAction.wasCompleted());
|
||||
assertEquals(0L, secondAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(1L, thirdAction.getExecutedCount());
|
||||
}
|
||||
|
||||
public void testExecuteThirdPhaseCompleted() throws Exception {
|
||||
MockIndexLifecycleContext context = new MockIndexLifecycleContext(indexName, thirdPhase.getName(), Phase.PHASE_COMPLETED,
|
||||
0, () -> 0L) {
|
||||
@Override
|
||||
public boolean canExecute(Phase phase) {
|
||||
throw new AssertionError("canExecute should not have been called");
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getNumberOfReplicas() {
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
||||
policy.execute(context);
|
||||
|
||||
assertEquals(indexName, context.getLifecycleTarget());
|
||||
assertEquals(thirdPhase.getName(), context.getPhase());
|
||||
assertEquals(Phase.PHASE_COMPLETED, context.getAction());
|
||||
|
||||
assertFalse(firstAction.wasCompleted());
|
||||
assertEquals(0L, firstAction.getExecutedCount());
|
||||
assertFalse(secondAction.wasCompleted());
|
||||
assertEquals(0L, secondAction.getExecutedCount());
|
||||
assertFalse(thirdAction.wasCompleted());
|
||||
assertEquals(0L, thirdAction.getExecutedCount());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue