Skip to content

Commit a679a1a

Browse files
authored
[8.x] [Failure Store] Expose failure store lifecycle information via the GET data stream API (#126668) (#127255)
* [Failure Store] Expose failure store lifecycle information via the `GET` data stream API (#126668) To retrieve the effective configuration you need to use the `GET` data streams API, for example, if a data stream has empty data stream options, it might still have failure store enabled from a cluster setting. The failure store is managed by default with a lifecycle with infinite (for now) retention, so the response will look like this: ``` GET _data_stream/* { "data_streams": [ { "name": "my-data-stream", "timestamp_field": { "name": "@timestamp" }, ..... "failure_store": { "enabled": true, "lifecycle": { "enabled": true }, "rollover_on_write": false, "indices": [ { "index_name": ".fs-my-data-stream-2099.03.08-000003", "index_uuid": "PA_JquKGSiKcAKBA8DJ5gw", "managed_by": "Data stream lifecycle" } ] } },... ] ``` In case there is a failure indexed managed by ILM the failure index info will be displayed as follows. ``` { "index_name": ".fs-my-data-stream-2099.03.08-000002", "index_uuid": "PA_JquKGSiKcAKBA8DJ5gw", "prefer_ilm": true, "ilm_policy": "my-lifecycle-policy", "managed_by": "Index Lifecycle Management" } ``` (cherry picked from commit db2992f) # Conflicts: # modules/data-streams/src/test/java/org/elasticsearch/datastreams/action/GetDataStreamsResponseTests.java # server/src/main/java/org/elasticsearch/action/datastreams/GetDataStreamAction.java * Ignore correctly the failure store response
1 parent 53f74eb commit a679a1a

File tree

5 files changed

+357
-51
lines changed

5 files changed

+357
-51
lines changed

docs/reference/data-streams/lifecycle/tutorial-migrate-data-stream-from-ilm-to-dsl.asciidoc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ PUT _index_template/dsl-data-stream-template
7272
----
7373
// TEST[continued]
7474

75-
We'll now index a document targetting `dsl-data-stream` to create the data stream
75+
We'll now index a document targeting `dsl-data-stream` to create the data stream
7676
and we'll also manually rollover the data stream to have another generation index created:
7777

7878
[source,console]
@@ -286,7 +286,7 @@ GET _data_stream/dsl-data-stream
286286
// TESTRESPONSE[s/"index_uuid": "xCEhwsp8Tey0-FLNFYVwSg"/"index_uuid": $body.data_streams.0.indices.0.index_uuid/]
287287
// TESTRESPONSE[s/"index_name": ".ds-dsl-data-stream-2023.10.19-000002"/"index_name": $body.data_streams.0.indices.1.index_name/]
288288
// TESTRESPONSE[s/"index_uuid": "PA_JquKGSiKcAKBA8DJ5gw"/"index_uuid": $body.data_streams.0.indices.1.index_uuid/]
289-
// TESTRESPONSE[s/"status": "GREEN"/"status": "YELLOW","failure_store":{"enabled": false, "indices": [], "rollover_on_write": true}/]
289+
// TESTRESPONSE[s/"status": "GREEN"/"status": "YELLOW","failure_store":$body.data_streams.0.failure_store/]
290290

291291
<1> The existing backing index will continue to be managed by {ilm-init}
292292
<2> The existing backing index will continue to be managed by {ilm-init}
@@ -368,7 +368,7 @@ GET _data_stream/dsl-data-stream
368368
// TESTRESPONSE[s/"index_uuid": "PA_JquKGSiKcAKBA8DJ5gw"/"index_uuid": $body.data_streams.0.indices.1.index_uuid/]
369369
// TESTRESPONSE[s/"index_name": ".ds-dsl-data-stream-2023.10.19-000003"/"index_name": $body.data_streams.0.indices.2.index_name/]
370370
// TESTRESPONSE[s/"index_uuid": "PA_JquKGSiKcAKBA8abcd1"/"index_uuid": $body.data_streams.0.indices.2.index_uuid/]
371-
// TESTRESPONSE[s/"status": "GREEN"/"status": "YELLOW","failure_store":{"enabled": false, "indices": [], "rollover_on_write": true}/]
371+
// TESTRESPONSE[s/"status": "GREEN"/"status": "YELLOW","failure_store":$body.data_streams.0.failure_store/]
372372

373373
<1> The backing indices that existed before rollover will continue to be managed by {ilm-init}
374374
<2> The backing indices that existed before rollover will continue to be managed by {ilm-init}
@@ -466,7 +466,7 @@ GET _data_stream/dsl-data-stream
466466
// TESTRESPONSE[s/"index_uuid": "PA_JquKGSiKcAKBA8DJ5gw"/"index_uuid": $body.data_streams.0.indices.1.index_uuid/]
467467
// TESTRESPONSE[s/"index_name": ".ds-dsl-data-stream-2023.10.19-000003"/"index_name": $body.data_streams.0.indices.2.index_name/]
468468
// TESTRESPONSE[s/"index_uuid": "PA_JquKGSiKcAKBA8abcd1"/"index_uuid": $body.data_streams.0.indices.2.index_uuid/]
469-
// TESTRESPONSE[s/"status": "GREEN"/"status": "YELLOW","failure_store":{"enabled": false, "indices": [], "rollover_on_write": true}/]
469+
// TESTRESPONSE[s/"status": "GREEN"/"status": "YELLOW","failure_store":$body.data_streams.0.failure_store/]
470470
<1> The write index is now managed by {ilm-init}
471471
<2> The `lifecycle` configured on the data stream is now disabled.
472472
<3> The next write index will be managed by {ilm-init}

modules/data-streams/src/main/java/org/elasticsearch/datastreams/rest/RestGetDataStreamsAction.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,11 @@ public class RestGetDataStreamsAction extends BaseRestHandler {
4444
)
4545
)
4646
);
47+
public static final String FAILURES_LIFECYCLE_API_CAPABILITY = "failure_store.lifecycle";
48+
private static final Set<String> CAPABILITIES = Set.of(
49+
DataStreamLifecycle.EFFECTIVE_RETENTION_REST_API_CAPABILITY,
50+
FAILURES_LIFECYCLE_API_CAPABILITY
51+
);
4752

4853
@Override
4954
public String getName() {
@@ -74,7 +79,7 @@ public boolean allowSystemIndexAccessByDefault() {
7479

7580
@Override
7681
public Set<String> supportedCapabilities() {
77-
return Set.of(DataStreamLifecycle.EFFECTIVE_RETENTION_REST_API_CAPABILITY);
82+
return CAPABILITIES;
7883
}
7984

8085
@Override

modules/data-streams/src/test/java/org/elasticsearch/datastreams/action/GetDataStreamsResponseTests.java

Lines changed: 80 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import static org.elasticsearch.cluster.metadata.DataStream.getDefaultBackingIndexName;
3939
import static org.elasticsearch.cluster.metadata.DataStream.getDefaultFailureStoreName;
4040
import static org.hamcrest.Matchers.is;
41+
import static org.hamcrest.Matchers.notNullValue;
4142
import static org.hamcrest.Matchers.nullValue;
4243

4344
public class GetDataStreamsResponseTests extends AbstractWireSerializingTestCase<Response> {
@@ -163,21 +164,16 @@ public void testResponseIlmAndDataStreamLifecycleRepresentation() throws Excepti
163164
is(ManagedBy.LIFECYCLE.displayValue)
164165
);
165166

166-
if (DataStream.isFailureStoreFeatureFlagEnabled()) {
167-
var failureStore = (Map<String, Object>) dataStreamMap.get(DataStream.FAILURE_STORE_FIELD.getPreferredName());
168-
List<Object> failureStoresRepresentation = (List<Object>) failureStore.get(DataStream.INDICES_FIELD.getPreferredName());
169-
Map<String, Object> failureStoreRepresentation = (Map<String, Object>) failureStoresRepresentation.get(0);
170-
assertThat(failureStoreRepresentation.get("index_name"), is(failureStoreIndex.getName()));
171-
assertThat(failureStoreRepresentation.get(Response.DataStreamInfo.PREFER_ILM.getPreferredName()), is(false));
172-
assertThat(
173-
failureStoreRepresentation.get(Response.DataStreamInfo.ILM_POLICY_FIELD.getPreferredName()),
174-
is(nullValue())
175-
);
176-
assertThat(
177-
failureStoreRepresentation.get(Response.DataStreamInfo.MANAGED_BY.getPreferredName()),
178-
is(ManagedBy.LIFECYCLE.displayValue)
179-
);
180-
}
167+
var failureStore = (Map<String, Object>) dataStreamMap.get(DataStream.FAILURE_STORE_FIELD.getPreferredName());
168+
List<Object> failureIndices = (List<Object>) failureStore.get(DataStream.INDICES_FIELD.getPreferredName());
169+
Map<String, Object> failureIndexRepresentation = (Map<String, Object>) failureIndices.get(0);
170+
assertThat(failureIndexRepresentation.get("index_name"), is(failureStoreIndex.getName()));
171+
assertThat(failureIndexRepresentation.get(Response.DataStreamInfo.PREFER_ILM.getPreferredName()), nullValue());
172+
assertThat(failureIndexRepresentation.get(Response.DataStreamInfo.ILM_POLICY_FIELD.getPreferredName()), is(nullValue()));
173+
assertThat(
174+
failureIndexRepresentation.get(Response.DataStreamInfo.MANAGED_BY.getPreferredName()),
175+
is(ManagedBy.LIFECYCLE.displayValue)
176+
);
181177
}
182178
}
183179

@@ -256,21 +252,75 @@ public void testResponseIlmAndDataStreamLifecycleRepresentation() throws Excepti
256252
is(ManagedBy.UNMANAGED.displayValue)
257253
);
258254

259-
if (DataStream.isFailureStoreFeatureFlagEnabled()) {
260-
var failureStore = (Map<String, Object>) dataStreamMap.get(DataStream.FAILURE_STORE_FIELD.getPreferredName());
261-
List<Object> failureStoresRepresentation = (List<Object>) failureStore.get(DataStream.INDICES_FIELD.getPreferredName());
262-
Map<String, Object> failureStoreRepresentation = (Map<String, Object>) failureStoresRepresentation.get(0);
263-
assertThat(failureStoreRepresentation.get("index_name"), is(failureStoreIndex.getName()));
264-
assertThat(failureStoreRepresentation.get(Response.DataStreamInfo.PREFER_ILM.getPreferredName()), is(false));
265-
assertThat(
266-
failureStoreRepresentation.get(Response.DataStreamInfo.ILM_POLICY_FIELD.getPreferredName()),
267-
is(nullValue())
268-
);
269-
assertThat(
270-
failureStoreRepresentation.get(Response.DataStreamInfo.MANAGED_BY.getPreferredName()),
271-
is(ManagedBy.UNMANAGED.displayValue)
272-
);
273-
}
255+
var failureStore = (Map<String, Object>) dataStreamMap.get(DataStream.FAILURE_STORE_FIELD.getPreferredName());
256+
List<Object> failureStoresRepresentation = (List<Object>) failureStore.get(DataStream.INDICES_FIELD.getPreferredName());
257+
Map<String, Object> failureStoreRepresentation = (Map<String, Object>) failureStoresRepresentation.get(0);
258+
assertThat(failureStoreRepresentation.get("index_name"), is(failureStoreIndex.getName()));
259+
assertThat(failureStoreRepresentation.get(Response.DataStreamInfo.PREFER_ILM.getPreferredName()), nullValue());
260+
assertThat(failureStoreRepresentation.get(Response.DataStreamInfo.ILM_POLICY_FIELD.getPreferredName()), is(nullValue()));
261+
assertThat(
262+
failureStoreRepresentation.get(Response.DataStreamInfo.MANAGED_BY.getPreferredName()),
263+
is(ManagedBy.UNMANAGED.displayValue)
264+
);
265+
}
266+
}
267+
268+
{
269+
// one failure index that have ILM policy
270+
DataStream logs = DataStream.builder("logs", indices)
271+
.setGeneration(3)
272+
.setAllowCustomRouting(true)
273+
.setIndexMode(IndexMode.STANDARD)
274+
.setLifecycle(DataStreamLifecycle.DEFAULT_DATA_LIFECYCLE)
275+
.setDataStreamOptions(DataStreamOptions.FAILURE_STORE_ENABLED)
276+
.setFailureIndices(DataStream.DataStreamIndices.failureIndicesBuilder(failureStores).build())
277+
.build();
278+
279+
String ilmPolicyName = "rollover-30days";
280+
Map<Index, Response.IndexProperties> indexSettingsValues = Map.of(
281+
firstGenerationIndex,
282+
new Response.IndexProperties(true, ilmPolicyName, ManagedBy.ILM),
283+
secondGenerationIndex,
284+
new Response.IndexProperties(false, ilmPolicyName, ManagedBy.LIFECYCLE),
285+
writeIndex,
286+
new Response.IndexProperties(true, null, ManagedBy.LIFECYCLE),
287+
failureStoreIndex,
288+
new Response.IndexProperties(randomBoolean(), ilmPolicyName, ManagedBy.LIFECYCLE)
289+
);
290+
291+
Response.DataStreamInfo dataStreamInfo = new Response.DataStreamInfo(
292+
logs,
293+
true,
294+
ClusterHealthStatus.GREEN,
295+
"index-template",
296+
null,
297+
null,
298+
indexSettingsValues,
299+
false,
300+
null
301+
);
302+
Response response = new Response(List.of(dataStreamInfo));
303+
XContentBuilder contentBuilder = XContentFactory.jsonBuilder();
304+
response.toXContent(contentBuilder, ToXContent.EMPTY_PARAMS);
305+
306+
BytesReference bytes = BytesReference.bytes(contentBuilder);
307+
try (XContentParser parser = createParser(JsonXContent.jsonXContent, bytes)) {
308+
Map<String, Object> map = parser.map();
309+
List<Object> dataStreams = (List<Object>) map.get(Response.DATA_STREAMS_FIELD.getPreferredName());
310+
assertThat(dataStreams.size(), is(1));
311+
Map<String, Object> dataStreamMap = (Map<String, Object>) dataStreams.get(0);
312+
assertThat(dataStreamMap.get(DataStream.NAME_FIELD.getPreferredName()), is(dataStreamName));
313+
314+
var failureStore = (Map<String, Object>) dataStreamMap.get(DataStream.FAILURE_STORE_FIELD.getPreferredName());
315+
List<Object> failureIndices = (List<Object>) failureStore.get(DataStream.INDICES_FIELD.getPreferredName());
316+
Map<String, Object> failureIndexRepresentation = (Map<String, Object>) failureIndices.get(0);
317+
assertThat(failureIndexRepresentation.get("index_name"), is(failureStoreIndex.getName()));
318+
assertThat(failureIndexRepresentation.get(Response.DataStreamInfo.PREFER_ILM.getPreferredName()), notNullValue());
319+
assertThat(failureIndexRepresentation.get(Response.DataStreamInfo.ILM_POLICY_FIELD.getPreferredName()), is(ilmPolicyName));
320+
assertThat(
321+
failureIndexRepresentation.get(Response.DataStreamInfo.MANAGED_BY.getPreferredName()),
322+
is(ManagedBy.LIFECYCLE.displayValue)
323+
);
274324
}
275325
}
276326
}

0 commit comments

Comments
 (0)