Skip to content

Add API for resetting state of a SystemIndexPlugin #69469

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 33 commits into from
Mar 17, 2021
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
77adad6
Stub out classes for reset feature states API
williamrandolph Jan 29, 2021
0a55d99
Add enough code to get an integration test working
williamrandolph Feb 2, 2021
51c8f8a
Improve unit test
williamrandolph Feb 2, 2021
581cd0a
Add rough version of callback to SystemIndexPlugin
williamrandolph Feb 3, 2021
d6fa39c
License changes
williamrandolph Feb 4, 2021
ca50e12
Use a HandledTransportAction for reset action
williamrandolph Feb 5, 2021
bf5c86a
Just use clusterService, client, and listener in callback
williamrandolph Feb 5, 2021
88ec70d
Add javadoc and update tests
williamrandolph Feb 5, 2021
eb03955
Fill out ResetFeatureStateResponse class
williamrandolph Feb 8, 2021
c5e82bc
Hook up response class in TransportAction
williamrandolph Feb 8, 2021
8cafd70
Rename inner class
williamrandolph Feb 9, 2021
e2af327
Add a second plugin to integration tests
williamrandolph Feb 10, 2021
1e4c3bd
Clean up code by using a GroupedActionListener
williamrandolph Feb 11, 2021
7b6c663
Merge branch 'master' into si/reset-features-api
williamrandolph Feb 23, 2021
237bc63
Add reset to list of non-operator actions
williamrandolph Feb 23, 2021
02a5937
Consolidate default deletion logic in SystemIndices.feature
williamrandolph Feb 24, 2021
83817e4
ML feature state cleaner
gwbrown Feb 23, 2021
5ea27d6
Implement Transform feature state reset
gwbrown Feb 25, 2021
b9b1833
Merge changes from master
williamrandolph Mar 2, 2021
1c7d174
Merge changes from master
williamrandolph Mar 2, 2021
db50f4d
Change endpoint to _feature/reset
williamrandolph Mar 2, 2021
6544c25
Add javadoc and cleanup java style
williamrandolph Mar 2, 2021
a61cf38
Merge branch 'si/reset-transforms' into si/reset-features-api
gwbrown Mar 2, 2021
44d0917
Add stub for API definition
williamrandolph Mar 3, 2021
76febcf
Merge branch 'si/reset-features-api' of github.com:williamrandolph/el…
williamrandolph Mar 4, 2021
3369131
Add stub for RHLC feature resetting
williamrandolph Mar 5, 2021
b18ff94
Implement client feature reset response parser
williamrandolph Mar 10, 2021
b316a91
Merge branch 'master' into si/reset-features-api
williamrandolph Mar 10, 2021
b05ec26
Merge branch 'master' into si/reset-features-api
williamrandolph Mar 15, 2021
d07d8c6
Respond to PR feedback
williamrandolph Mar 15, 2021
746f43c
Change _features/reset path to _features/_reset
williamrandolph Mar 15, 2021
8c97adb
Checkstyle fixes
williamrandolph Mar 15, 2021
71bd331
Merge branch 'master' into si/reset-features-api
elasticmachine Mar 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"features.reset_features":{
"documentation":{
"url":"https://www.elastic.co/guide/en/elasticsearch/reference/master/modules-snapshots.html",
"description":"Resets the internal state of features, usually by deleting system indices"
},
"stability":"experimental",
"visibility":"public",
"headers":{
"accept": [ "application/json"]
},
"url":{
"paths":[
{
"path":"/_features/reset",
"methods":[
"POST"
]
}
]
},
"params":{
"master_timeout":{
"type":"time",
"description":"Explicit operation timeout for connection to master node"
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"Get Features":
- skip:
features: contains
version: " - 7.99.99" # Adjust this after backport
reason: "This API was added in 7.13.0"
- do: { features.get_features: {}}
- contains: {'features': {'name': 'tasks'}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.snapshots;

import org.elasticsearch.action.admin.cluster.snapshots.features.ResetFeatureStateAction;
import org.elasticsearch.action.admin.cluster.snapshots.features.ResetFeatureStateRequest;
import org.elasticsearch.action.admin.cluster.snapshots.features.ResetFeatureStateResponse;
import org.elasticsearch.action.admin.indices.get.GetIndexResponse;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.IndexNotFoundException;
import org.elasticsearch.indices.SystemIndexDescriptor;
import org.elasticsearch.plugins.Plugin;
import org.elasticsearch.plugins.SystemIndexPlugin;
import org.elasticsearch.test.ESIntegTestCase;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

import static org.hamcrest.Matchers.arrayContaining;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;

public class FeatureStateResetApiIT extends ESIntegTestCase {

@Override
protected Collection<Class<? extends Plugin>> nodePlugins() {
List<Class<? extends Plugin>> plugins = new ArrayList<>(super.nodePlugins());
plugins.add(SystemIndexTestPlugin.class);
plugins.add(SecondSystemIndexTestPlugin.class);
return plugins;
}

/** Check that the reset method cleans up a feature */
public void testResetSystemIndices() throws Exception {
String systemIndex1 = ".test-system-idx-1";
String systemIndex2 = ".second-test-system-idx-1";
String associatedIndex = ".associated-idx-1";

// put a document in a system index
indexDoc(systemIndex1, "1", "purpose", "system index doc");
refresh(systemIndex1);

// put a document in a second system index
indexDoc(systemIndex2, "1", "purpose", "second system index doc");
refresh(systemIndex2);

// put a document in associated index
indexDoc(associatedIndex, "1", "purpose", "associated index doc");
refresh(associatedIndex);

// put a document in a normal index
indexDoc("my_index", "1", "purpose", "normal index doc");
refresh("my_index");

// call the reset API
ResetFeatureStateResponse apiResponse = client().execute(ResetFeatureStateAction.INSTANCE, new ResetFeatureStateRequest()).get();
assertThat(apiResponse.getItemList(), containsInAnyOrder(
new ResetFeatureStateResponse.ResetFeatureStateStatus("SystemIndexTestPlugin", "SUCCESS"),
new ResetFeatureStateResponse.ResetFeatureStateStatus("SecondSystemIndexTestPlugin", "SUCCESS"),
new ResetFeatureStateResponse.ResetFeatureStateStatus("tasks", "SUCCESS")
));

// verify that both indices are gone
Exception e1 = expectThrows(IndexNotFoundException.class, () -> client().admin().indices().prepareGetIndex()
.addIndices(systemIndex1)
.get());

assertThat(e1.getMessage(), containsString("no such index"));

Exception e2 = expectThrows(IndexNotFoundException.class, () -> client().admin().indices().prepareGetIndex()
.addIndices(associatedIndex)
.get());

assertThat(e2.getMessage(), containsString("no such index"));

Exception e3 = expectThrows(IndexNotFoundException.class, () -> client().admin().indices().prepareGetIndex()
.addIndices(systemIndex2)
.get());

assertThat(e3.getMessage(), containsString("no such index"));

GetIndexResponse response = client().admin().indices().prepareGetIndex()
.addIndices("my_index")
.get();

assertThat(response.getIndices(), arrayContaining("my_index"));
}

/**
* A test plugin with patterns for system indices and associated indices.
*/
public static class SystemIndexTestPlugin extends Plugin implements SystemIndexPlugin {

public static final String SYSTEM_INDEX_PATTERN = ".test-system-idx*";
public static final String ASSOCIATED_INDEX_PATTERN = ".associated-idx*";

@Override
public Collection<SystemIndexDescriptor> getSystemIndexDescriptors(Settings settings) {
return Collections.singletonList(new SystemIndexDescriptor(SYSTEM_INDEX_PATTERN, "System indices for tests"));
}

@Override
public Collection<String> getAssociatedIndexPatterns() {
return Collections.singletonList(ASSOCIATED_INDEX_PATTERN);
}

@Override
public String getFeatureName() {
return SystemIndexTestPlugin.class.getSimpleName();
}

@Override
public String getFeatureDescription() {
return "A simple test plugin";
}
}

/**
* A second test plugin with a patterns for system indices.
*/
public static class SecondSystemIndexTestPlugin extends Plugin implements SystemIndexPlugin {

public static final String SYSTEM_INDEX_PATTERN = ".second-test-system-idx*";

@Override
public Collection<SystemIndexDescriptor> getSystemIndexDescriptors(Settings settings) {
return Collections.singletonList(new SystemIndexDescriptor(SYSTEM_INDEX_PATTERN, "System indices for tests"));
}

@Override
public String getFeatureName() {
return SecondSystemIndexTestPlugin.class.getSimpleName();
}

@Override
public String getFeatureDescription() {
return "A second test plugin";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,9 @@
import org.elasticsearch.action.admin.cluster.snapshots.create.TransportCreateSnapshotAction;
import org.elasticsearch.action.admin.cluster.snapshots.delete.DeleteSnapshotAction;
import org.elasticsearch.action.admin.cluster.snapshots.delete.TransportDeleteSnapshotAction;
import org.elasticsearch.action.admin.cluster.snapshots.features.ResetFeatureStateAction;
import org.elasticsearch.action.admin.cluster.snapshots.features.SnapshottableFeaturesAction;
import org.elasticsearch.action.admin.cluster.snapshots.features.TransportResetFeatureStateAction;
import org.elasticsearch.action.admin.cluster.snapshots.features.TransportSnapshottableFeaturesAction;
import org.elasticsearch.action.admin.cluster.snapshots.get.GetSnapshotsAction;
import org.elasticsearch.action.admin.cluster.snapshots.get.TransportGetSnapshotsAction;
Expand Down Expand Up @@ -282,6 +284,7 @@
import org.elasticsearch.rest.action.admin.cluster.RestPutStoredScriptAction;
import org.elasticsearch.rest.action.admin.cluster.RestReloadSecureSettingsAction;
import org.elasticsearch.rest.action.admin.cluster.RestRemoteClusterInfoAction;
import org.elasticsearch.rest.action.admin.cluster.RestResetFeatureStateAction;
import org.elasticsearch.rest.action.admin.cluster.RestRestoreSnapshotAction;
import org.elasticsearch.rest.action.admin.cluster.RestSnapshotsStatusAction;
import org.elasticsearch.rest.action.admin.cluster.RestSnapshottableFeaturesAction;
Expand Down Expand Up @@ -501,6 +504,7 @@ public <Request extends ActionRequest, Response extends ActionResponse> void reg
actions.register(RestoreSnapshotAction.INSTANCE, TransportRestoreSnapshotAction.class);
actions.register(SnapshotsStatusAction.INSTANCE, TransportSnapshotsStatusAction.class);
actions.register(SnapshottableFeaturesAction.INSTANCE, TransportSnapshottableFeaturesAction.class);
actions.register(ResetFeatureStateAction.INSTANCE, TransportResetFeatureStateAction.class);

actions.register(IndicesStatsAction.INSTANCE, TransportIndicesStatsAction.class);
actions.register(IndicesSegmentsAction.INSTANCE, TransportIndicesSegmentsAction.class);
Expand Down Expand Up @@ -651,6 +655,7 @@ public void initRestHandlers(Supplier<DiscoveryNodes> nodesInCluster) {
registerHandler.accept(new RestDeleteSnapshotAction());
registerHandler.accept(new RestSnapshotsStatusAction());
registerHandler.accept(new RestSnapshottableFeaturesAction());
registerHandler.accept(new RestResetFeatureStateAction());
registerHandler.accept(new RestGetIndicesAction());
registerHandler.accept(new RestIndicesStatsAction());
registerHandler.accept(new RestIndicesSegmentsAction(threadPool));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.action.admin.cluster.snapshots.features;

import org.elasticsearch.action.ActionType;

/** Action for resetting feature states, mostly meaning system indices */
public class ResetFeatureStateAction extends ActionType<ResetFeatureStateResponse> {

public static final ResetFeatureStateAction INSTANCE = new ResetFeatureStateAction();
public static final String NAME = "cluster:admin/features/reset";

private ResetFeatureStateAction() {
super(NAME, ResetFeatureStateResponse::new);
}
}
Original file line number Diff line number Diff line change
@@ -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
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

package org.elasticsearch.action.admin.cluster.snapshots.features;

import org.elasticsearch.action.ActionRequest;
import org.elasticsearch.action.ActionRequestValidationException;
import org.elasticsearch.common.io.stream.StreamInput;
import org.elasticsearch.common.io.stream.StreamOutput;

import java.io.IOException;

/** Request for resetting feature state */
public class ResetFeatureStateRequest extends ActionRequest {

public ResetFeatureStateRequest() {
// TODO[wrb] - We might need to let this request take a list of
// feature state names, but not for the initial implementation
}

public ResetFeatureStateRequest(StreamInput in) throws IOException {
super(in);
}

@Override
public void writeTo(StreamOutput out) throws IOException {
super.writeTo(out);
}

@Override
public ActionRequestValidationException validate() {
return null;
}
}
Loading