Provide useful error when a policy doesn't exist (#34206)
When an index is configured to use a lifecycle policy that does not exist, this will now be noted in the step_info for that policy.
This commit is contained in:
parent
d66a63ed7a
commit
13d89295c8
|
@ -96,9 +96,14 @@ public class IndexLifecycleRunner {
|
|||
}
|
||||
Step currentStep = getCurrentStep(stepRegistry, policy, indexMetaData, lifecycleState);
|
||||
if (currentStep == null) {
|
||||
logger.warn("current step [{}] for index [{}] with policy [{}] is not recognized",
|
||||
getCurrentStepKey(lifecycleState), index, policy);
|
||||
return;
|
||||
if (stepRegistry.policyExists(policy) == false) {
|
||||
markPolicyDoesNotExist(policy, indexMetaData.getIndex(), lifecycleState);
|
||||
return;
|
||||
} else {
|
||||
logger.error("current step [{}] for index [{}] with policy [{}] is not recognized",
|
||||
getCurrentStepKey(lifecycleState), index, policy);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentStep instanceof TerminalPolicyStep) {
|
||||
|
@ -197,9 +202,14 @@ public class IndexLifecycleRunner {
|
|||
}
|
||||
Step currentStep = getCurrentStep(stepRegistry, policy, indexMetaData, lifecycleState);
|
||||
if (currentStep == null) {
|
||||
logger.warn("current step [{}] for index [{}] with policy [{}] is not recognized",
|
||||
getCurrentStepKey(lifecycleState), index, policy);
|
||||
return;
|
||||
if (stepRegistry.policyExists(policy) == false) {
|
||||
markPolicyDoesNotExist(policy, indexMetaData.getIndex(), lifecycleState);
|
||||
return;
|
||||
} else {
|
||||
logger.error("current step [{}] for index [{}] with policy [{}] is not recognized",
|
||||
getCurrentStepKey(lifecycleState), index, policy);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentStep instanceof TerminalPolicyStep) {
|
||||
|
@ -536,4 +546,12 @@ public class IndexLifecycleRunner {
|
|||
builder.removeCustom(ILM_CUSTOM_METADATA_KEY);
|
||||
return builder.settings(newSettings);
|
||||
}
|
||||
|
||||
private void markPolicyDoesNotExist(String policyName, Index index, LifecycleExecutionState executionState) {
|
||||
logger.debug("policy [{}] for index [{}] does not exist, recording this in step_info for this index",
|
||||
policyName, index.getName());
|
||||
setStepInfo(index, policyName, getCurrentStepKey(executionState),
|
||||
new SetStepInfoUpdateTask.ExceptionWrapper(
|
||||
new IllegalArgumentException("policy [" + policyName + "] does not exist")));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -227,6 +227,10 @@ public class PolicyStepsRegistry {
|
|||
}
|
||||
}
|
||||
|
||||
public boolean policyExists(final String policy) {
|
||||
return lifecyclePolicyMap.containsKey(policy);
|
||||
}
|
||||
|
||||
public Step getFirstStep(String policy) {
|
||||
return firstStepMap.get(policy);
|
||||
}
|
||||
|
|
|
@ -12,12 +12,14 @@ import org.elasticsearch.cluster.ClusterStateUpdateTask;
|
|||
import org.elasticsearch.cluster.metadata.IndexMetaData;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.xcontent.ToXContentObject;
|
||||
import org.elasticsearch.common.xcontent.XContentBuilder;
|
||||
import org.elasticsearch.index.Index;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleExecutionState;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.LifecycleSettings;
|
||||
import org.elasticsearch.xpack.core.indexlifecycle.Step;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Objects;
|
||||
|
||||
public class SetStepInfoUpdateTask extends ClusterStateUpdateTask {
|
||||
private final Index index;
|
||||
|
@ -58,7 +60,7 @@ public class SetStepInfoUpdateTask extends ClusterStateUpdateTask {
|
|||
Settings indexSettings = idxMeta.getSettings();
|
||||
LifecycleExecutionState indexILMData = LifecycleExecutionState.fromIndexMetadata(idxMeta);
|
||||
if (policy.equals(LifecycleSettings.LIFECYCLE_NAME_SETTING.get(indexSettings))
|
||||
&& currentStepKey.equals(IndexLifecycleRunner.getCurrentStepKey(indexILMData))) {
|
||||
&& Objects.equals(currentStepKey, IndexLifecycleRunner.getCurrentStepKey(indexILMData))) {
|
||||
return IndexLifecycleRunner.addStepInfoToClusterState(index, currentState, stepInfo);
|
||||
} else {
|
||||
// either the policy has changed or the step is now
|
||||
|
@ -73,4 +75,20 @@ public class SetStepInfoUpdateTask extends ClusterStateUpdateTask {
|
|||
throw new ElasticsearchException("policy [" + policy + "] for index [" + index.getName()
|
||||
+ "] failed trying to set step info for step [" + currentStepKey + "].", e);
|
||||
}
|
||||
|
||||
public static class ExceptionWrapper implements ToXContentObject {
|
||||
private final Throwable exception;
|
||||
|
||||
public ExceptionWrapper(Throwable exception) {
|
||||
this.exception = exception;
|
||||
}
|
||||
|
||||
@Override
|
||||
public XContentBuilder toXContent(XContentBuilder builder, Params params) throws IOException {
|
||||
builder.startObject();
|
||||
ElasticsearchException.generateThrowableXContent(builder, params, exception);
|
||||
builder.endObject();
|
||||
return builder;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -511,7 +511,7 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
|
|||
Mockito.verifyZeroInteractions(clusterService);
|
||||
}
|
||||
|
||||
public void testRunPolicyWithNoStepsInRegistry() {
|
||||
public void testRunPolicyThatDoesntExist() {
|
||||
String policyName = "cluster_state_action_policy";
|
||||
ClusterService clusterService = mock(ClusterService.class);
|
||||
IndexLifecycleRunner runner = new IndexLifecycleRunner(new PolicyStepsRegistry(NamedXContentRegistry.EMPTY, null),
|
||||
|
@ -520,7 +520,16 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
|
|||
.numberOfShards(randomIntBetween(1, 5)).numberOfReplicas(randomIntBetween(0, 5)).build();
|
||||
// verify that no exception is thrown
|
||||
runner.runPolicyAfterStateChange(policyName, indexMetaData);
|
||||
Mockito.verifyZeroInteractions(clusterService);
|
||||
Mockito.verify(clusterService, Mockito.times(1)).submitStateUpdateTask(Mockito.matches("ilm-set-step-info"),
|
||||
Mockito.argThat(new SetStepInfoUpdateTaskMatcher(indexMetaData.getIndex(), policyName, null,
|
||||
(builder, params) -> {
|
||||
builder.startObject();
|
||||
builder.field("reason", "policy [does_not_exist] does not exist");
|
||||
builder.field("type", "illegal_argument_exception");
|
||||
builder.endObject();
|
||||
return builder;
|
||||
})));
|
||||
Mockito.verifyNoMoreInteractions(clusterService);
|
||||
}
|
||||
|
||||
public void testGetCurrentStepKey() {
|
||||
|
@ -1602,7 +1611,17 @@ public class IndexLifecycleRunnerTests extends ESTestCase {
|
|||
return Objects.equals(index, task.getIndex()) &&
|
||||
Objects.equals(policy, task.getPolicy())&&
|
||||
Objects.equals(currentStepKey, task.getCurrentStepKey()) &&
|
||||
Objects.equals(stepInfo, task.getStepInfo());
|
||||
Objects.equals(xContentToString(stepInfo), xContentToString(task.getStepInfo()));
|
||||
}
|
||||
|
||||
private String xContentToString(ToXContentObject xContent) {
|
||||
try {
|
||||
XContentBuilder builder = JsonXContent.contentBuilder();
|
||||
stepInfo.toXContent(builder, ToXContent.EMPTY_PARAMS);
|
||||
return BytesReference.bytes(builder).utf8ToString();
|
||||
} catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -238,6 +238,60 @@ public class TimeSeriesLifecycleActionsIT extends ESRestTestCase {
|
|||
expectThrows(ResponseException.class, this::indexDocument);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void testNonexistentPolicy() throws Exception {
|
||||
String indexPrefix = randomAlphaOfLengthBetween(5,15).toLowerCase(Locale.ROOT);
|
||||
final StringEntity template = new StringEntity("{\n" +
|
||||
" \"index_patterns\": \"" + indexPrefix + "*\",\n" +
|
||||
" \"settings\": {\n" +
|
||||
" \"index\": {\n" +
|
||||
" \"lifecycle\": {\n" +
|
||||
" \"name\": \"does_not_exist\",\n" +
|
||||
" \"rollover_alias\": \"test_alias\"\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}", ContentType.APPLICATION_JSON);
|
||||
Request templateRequest = new Request("PUT", "_template/test");
|
||||
templateRequest.setEntity(template);
|
||||
client().performRequest(templateRequest);
|
||||
|
||||
policy = randomAlphaOfLengthBetween(5,20);
|
||||
createNewSingletonPolicy("hot", new RolloverAction(null, null, 1L));
|
||||
|
||||
index = indexPrefix + "-000001";
|
||||
final StringEntity putIndex = new StringEntity("{\n" +
|
||||
" \"aliases\": {\n" +
|
||||
" \"test_alias\": {\n" +
|
||||
" \"is_write_index\": true\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
"}", ContentType.APPLICATION_JSON);
|
||||
Request putIndexRequest = new Request("PUT", index);
|
||||
putIndexRequest.setEntity(putIndex);
|
||||
client().performRequest(putIndexRequest);
|
||||
indexDocument();
|
||||
|
||||
assertBusy(() -> {
|
||||
Request explainRequest = new Request("GET", index + "/_ilm/explain");
|
||||
Response response = client().performRequest(explainRequest);
|
||||
Map<String, Object> responseMap;
|
||||
try (InputStream is = response.getEntity().getContent()) {
|
||||
responseMap = XContentHelper.convertToMap(XContentType.JSON.xContent(), is, true);
|
||||
}
|
||||
logger.info(responseMap);
|
||||
Map<String, Object> indexStatus = (Map<String, Object>)((Map<String, Object>) responseMap.get("indices")).get(index);
|
||||
assertNull(indexStatus.get("phase"));
|
||||
assertNull(indexStatus.get("action"));
|
||||
assertNull(indexStatus.get("step"));
|
||||
assertEquals("policy [does_not_exist] does not exist",
|
||||
((Map<String, String>)indexStatus.get("step_info")).get("reason"));
|
||||
assertEquals("illegal_argument_exception",
|
||||
((Map<String, String>)indexStatus.get("step_info")).get("type"));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void createNewSingletonPolicy(String phaseName, LifecycleAction action) throws IOException {
|
||||
createNewSingletonPolicy(phaseName, action, TimeValue.ZERO);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue