Migrate the reserved repository action to be per-project (#130155)
Resolves: ES-10479
This commit is contained in:
parent
f3c5eb7815
commit
c17bfcbfc2
|
@ -85,4 +85,16 @@ public class TransportDeleteRepositoryAction extends AcknowledgedTransportMaster
|
|||
public Set<String> modifiedKeys(DeleteRepositoryRequest request) {
|
||||
return Set.of(request.name());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateForReservedState(DeleteRepositoryRequest request, ClusterState state) {
|
||||
super.validateForReservedState(request, state);
|
||||
|
||||
validateForReservedState(
|
||||
projectResolver.getProjectMetadata(state).reservedStateMetadata().values(),
|
||||
reservedStateHandlerName().get(),
|
||||
modifiedKeys(request),
|
||||
request.toString()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,9 +12,8 @@ package org.elasticsearch.action.admin.cluster.repositories.reservedstate;
|
|||
import org.elasticsearch.action.admin.cluster.repositories.put.PutRepositoryRequest;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.ProjectId;
|
||||
import org.elasticsearch.core.FixForMultiProject;
|
||||
import org.elasticsearch.repositories.RepositoriesService;
|
||||
import org.elasticsearch.reservedstate.ReservedClusterStateHandler;
|
||||
import org.elasticsearch.reservedstate.ReservedProjectStateHandler;
|
||||
import org.elasticsearch.reservedstate.TransformState;
|
||||
import org.elasticsearch.xcontent.XContentParser;
|
||||
import org.elasticsearch.xcontent.XContentParserConfiguration;
|
||||
|
@ -36,7 +35,7 @@ import static org.elasticsearch.common.xcontent.XContentHelper.mapToXContentPars
|
|||
* It is used by the ReservedClusterStateService to add/update or remove snapshot repositories. Typical usage
|
||||
* for this action is in the context of file based settings.
|
||||
*/
|
||||
public class ReservedRepositoryAction implements ReservedClusterStateHandler<List<PutRepositoryRequest>> {
|
||||
public class ReservedRepositoryAction implements ReservedProjectStateHandler<List<PutRepositoryRequest>> {
|
||||
public static final String NAME = "snapshot_repositories";
|
||||
|
||||
private final RepositoriesService repositoriesService;
|
||||
|
@ -56,14 +55,12 @@ public class ReservedRepositoryAction implements ReservedClusterStateHandler<Lis
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Collection<PutRepositoryRequest> prepare(Object input) {
|
||||
public Collection<PutRepositoryRequest> prepare(ProjectId projectId, Object input) {
|
||||
List<PutRepositoryRequest> repositories = (List<PutRepositoryRequest>) input;
|
||||
|
||||
for (var repositoryRequest : repositories) {
|
||||
validate(repositoryRequest);
|
||||
RepositoriesService.validateRepositoryName(repositoryRequest.name());
|
||||
@FixForMultiProject(description = "resolve the actual projectId, ES-10479")
|
||||
final var projectId = ProjectId.DEFAULT;
|
||||
repositoriesService.validateRepositoryCanBeCreated(projectId, repositoryRequest);
|
||||
}
|
||||
|
||||
|
@ -71,13 +68,11 @@ public class ReservedRepositoryAction implements ReservedClusterStateHandler<Lis
|
|||
}
|
||||
|
||||
@Override
|
||||
public TransformState transform(List<PutRepositoryRequest> source, TransformState prevState) throws Exception {
|
||||
var requests = prepare(source);
|
||||
public TransformState transform(ProjectId projectId, List<PutRepositoryRequest> source, TransformState prevState) throws Exception {
|
||||
var requests = prepare(projectId, source);
|
||||
|
||||
ClusterState state = prevState.state();
|
||||
|
||||
@FixForMultiProject(description = "resolve the actual projectId, ES-10479")
|
||||
final var projectId = ProjectId.DEFAULT;
|
||||
for (var request : requests) {
|
||||
RepositoriesService.RegisterRepositoryTask task = new RepositoriesService.RegisterRepositoryTask(
|
||||
repositoriesService,
|
||||
|
|
|
@ -1125,7 +1125,7 @@ class NodeConstruction {
|
|||
indicesService
|
||||
);
|
||||
|
||||
actionModule.getReservedClusterStateService().installClusterStateHandler(new ReservedRepositoryAction(repositoriesService));
|
||||
actionModule.getReservedClusterStateService().installProjectStateHandler(new ReservedRepositoryAction(repositoriesService));
|
||||
actionModule.getReservedClusterStateService().installProjectStateHandler(new ReservedPipelineAction());
|
||||
|
||||
var fileSettingsHealthIndicatorPublisher = new FileSettingsService.FileSettingsHealthIndicatorPublisherImpl(clusterService, client);
|
||||
|
|
|
@ -14,6 +14,7 @@ import org.elasticsearch.client.internal.node.NodeClient;
|
|||
import org.elasticsearch.cluster.ClusterName;
|
||||
import org.elasticsearch.cluster.ClusterState;
|
||||
import org.elasticsearch.cluster.metadata.ProjectId;
|
||||
import org.elasticsearch.cluster.metadata.ProjectMetadata;
|
||||
import org.elasticsearch.cluster.metadata.RepositoryMetadata;
|
||||
import org.elasticsearch.cluster.service.ClusterService;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
|
@ -34,7 +35,6 @@ import java.util.Set;
|
|||
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
|
@ -44,9 +44,10 @@ import static org.mockito.Mockito.spy;
|
|||
*/
|
||||
public class ReservedRepositoryActionTests extends ESTestCase {
|
||||
|
||||
private TransformState processJSON(ReservedRepositoryAction action, TransformState prevState, String json) throws Exception {
|
||||
private TransformState processJSON(ProjectId projectId, ReservedRepositoryAction action, TransformState prevState, String json)
|
||||
throws Exception {
|
||||
try (XContentParser parser = XContentType.JSON.xContent().createParser(XContentParserConfiguration.EMPTY, json)) {
|
||||
return action.transform(action.fromXContent(parser), prevState);
|
||||
return action.transform(projectId, action.fromXContent(parser), prevState);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -69,20 +70,24 @@ public class ReservedRepositoryActionTests extends ESTestCase {
|
|||
|
||||
assertEquals(
|
||||
"[repo] repository type [inter_planetary] does not exist",
|
||||
expectThrows(RepositoryException.class, () -> processJSON(action, prevState, badPolicyJSON)).getMessage()
|
||||
expectThrows(RepositoryException.class, () -> processJSON(randomProjectIdOrDefault(), action, prevState, badPolicyJSON))
|
||||
.getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
public void testAddRepo() throws Exception {
|
||||
var repositoriesService = mockRepositoriesService();
|
||||
final var projectId = randomProjectIdOrDefault();
|
||||
|
||||
ClusterState state = ClusterState.builder(new ClusterName("elasticsearch")).build();
|
||||
ClusterState state = ClusterState.builder(new ClusterName("elasticsearch"))
|
||||
.putProjectMetadata(ProjectMetadata.builder(projectId))
|
||||
.build();
|
||||
TransformState prevState = new TransformState(state, Collections.emptySet());
|
||||
ReservedRepositoryAction action = new ReservedRepositoryAction(repositoriesService);
|
||||
|
||||
String emptyJSON = "";
|
||||
|
||||
TransformState updatedState = processJSON(action, prevState, emptyJSON);
|
||||
TransformState updatedState = processJSON(projectId, action, prevState, emptyJSON);
|
||||
assertEquals(0, updatedState.keys().size());
|
||||
assertEquals(prevState.state(), updatedState.state());
|
||||
|
||||
|
@ -103,14 +108,17 @@ public class ReservedRepositoryActionTests extends ESTestCase {
|
|||
}""";
|
||||
|
||||
prevState = updatedState;
|
||||
updatedState = processJSON(action, prevState, settingsJSON);
|
||||
updatedState = processJSON(projectId, action, prevState, settingsJSON);
|
||||
assertThat(updatedState.keys(), containsInAnyOrder("repo", "repo1"));
|
||||
}
|
||||
|
||||
public void testRemoveRepo() {
|
||||
var repositoriesService = mockRepositoriesService();
|
||||
final var projectId = randomProjectIdOrDefault();
|
||||
|
||||
ClusterState state = ClusterState.builder(new ClusterName("elasticsearch")).build();
|
||||
ClusterState state = ClusterState.builder(new ClusterName("elasticsearch"))
|
||||
.putProjectMetadata(ProjectMetadata.builder(projectId))
|
||||
.build();
|
||||
TransformState prevState = new TransformState(state, Set.of("repo1"));
|
||||
ReservedRepositoryAction action = new ReservedRepositoryAction(repositoriesService);
|
||||
|
||||
|
@ -120,7 +128,7 @@ public class ReservedRepositoryActionTests extends ESTestCase {
|
|||
// missing is sufficient to tell that we attempted to delete that repo
|
||||
assertEquals(
|
||||
"[repo1] missing",
|
||||
expectThrows(RepositoryMissingException.class, () -> processJSON(action, prevState, emptyJSON)).getMessage()
|
||||
expectThrows(RepositoryMissingException.class, () -> processJSON(projectId, action, prevState, emptyJSON)).getMessage()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -153,7 +161,7 @@ public class ReservedRepositoryActionTests extends ESTestCase {
|
|||
throw new RepositoryException(request.name(), "repository type [" + request.type() + "] does not exist");
|
||||
}
|
||||
return null;
|
||||
}).when(repositoriesService).validateRepositoryCanBeCreated(eq(ProjectId.DEFAULT), any());
|
||||
}).when(repositoriesService).validateRepositoryCanBeCreated(any(ProjectId.class), any());
|
||||
|
||||
return repositoriesService;
|
||||
}
|
||||
|
|
|
@ -290,8 +290,8 @@ public class ReservedSnapshotLifecycleStateServiceTests extends ESTestCase {
|
|||
ReservedClusterStateService controller = new ReservedClusterStateService(
|
||||
clusterService,
|
||||
null,
|
||||
List.of(new ReservedClusterSettingsAction(clusterSettings), new ReservedRepositoryAction(repositoriesService)),
|
||||
List.of()
|
||||
List.of(new ReservedClusterSettingsAction(clusterSettings)),
|
||||
List.of(new ReservedRepositoryAction(repositoriesService))
|
||||
);
|
||||
|
||||
String testJSON = """
|
||||
|
@ -362,12 +362,8 @@ public class ReservedSnapshotLifecycleStateServiceTests extends ESTestCase {
|
|||
controller = new ReservedClusterStateService(
|
||||
clusterService,
|
||||
null,
|
||||
List.of(
|
||||
new ReservedClusterSettingsAction(clusterSettings),
|
||||
new ReservedSnapshotAction(),
|
||||
new ReservedRepositoryAction(repositoriesService)
|
||||
),
|
||||
List.of()
|
||||
List.of(new ReservedClusterSettingsAction(clusterSettings), new ReservedSnapshotAction()),
|
||||
List.of(new ReservedRepositoryAction(repositoriesService))
|
||||
);
|
||||
|
||||
try (XContentParser parser = XContentType.JSON.xContent().createParser(XContentParserConfiguration.EMPTY, testJSON)) {
|
||||
|
|
Loading…
Reference in New Issue