forked from elastic/elasticsearch
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Distinguish "missing repository" from "missing repository plugin" (el…
…astic#82457) Currently it is possible to uninstall repository plugin before deleting repository that uses it. In such case the repository is still listed in the API however every interaction with it produces the "no such repository" exception. This is very confusing. This change updates the error message to correctly point the root of the issue.
- Loading branch information
1 parent
7018e9e
commit 75579f7
Showing
5 changed files
with
327 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
187 changes: 187 additions & 0 deletions
187
server/src/main/java/org/elasticsearch/repositories/UnknownTypeRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,187 @@ | ||
/* | ||
* 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.repositories; | ||
|
||
import org.elasticsearch.Version; | ||
import org.elasticsearch.action.ActionListener; | ||
import org.elasticsearch.cluster.ClusterState; | ||
import org.elasticsearch.cluster.ClusterStateUpdateTask; | ||
import org.elasticsearch.cluster.metadata.IndexMetadata; | ||
import org.elasticsearch.cluster.metadata.Metadata; | ||
import org.elasticsearch.cluster.metadata.RepositoryMetadata; | ||
import org.elasticsearch.cluster.node.DiscoveryNode; | ||
import org.elasticsearch.common.component.AbstractLifecycleComponent; | ||
import org.elasticsearch.index.shard.ShardId; | ||
import org.elasticsearch.index.snapshots.IndexShardSnapshotStatus; | ||
import org.elasticsearch.index.store.Store; | ||
import org.elasticsearch.indices.recovery.RecoveryState; | ||
import org.elasticsearch.snapshots.SnapshotId; | ||
|
||
import java.io.IOException; | ||
import java.util.Collection; | ||
import java.util.function.Consumer; | ||
import java.util.function.Function; | ||
|
||
/** | ||
* This class represents a repository that could not be initialized due to unknown type. | ||
* This could happen whe a user creates a snapshot repository using a type from a plugin and then removes the plugin. | ||
*/ | ||
public class UnknownTypeRepository extends AbstractLifecycleComponent implements Repository { | ||
|
||
private final RepositoryMetadata repositoryMetadata; | ||
|
||
public UnknownTypeRepository(RepositoryMetadata repositoryMetadata) { | ||
this.repositoryMetadata = repositoryMetadata; | ||
} | ||
|
||
private RepositoryException createUnknownTypeException() { | ||
return new RepositoryException( | ||
repositoryMetadata.name(), | ||
"repository type [" + repositoryMetadata.type() + "] is unknown; ensure that all required plugins are installed on this node" | ||
); | ||
} | ||
|
||
@Override | ||
public RepositoryMetadata getMetadata() { | ||
return repositoryMetadata; | ||
} | ||
|
||
@Override | ||
public void getSnapshotInfo(GetSnapshotInfoContext context) { | ||
throw createUnknownTypeException(); | ||
} | ||
|
||
@Override | ||
public Metadata getSnapshotGlobalMetadata(SnapshotId snapshotId) { | ||
throw createUnknownTypeException(); | ||
} | ||
|
||
@Override | ||
public IndexMetadata getSnapshotIndexMetaData(RepositoryData repositoryData, SnapshotId snapshotId, IndexId index) throws IOException { | ||
throw createUnknownTypeException(); | ||
} | ||
|
||
@Override | ||
public void getRepositoryData(ActionListener<RepositoryData> listener) { | ||
listener.onFailure(createUnknownTypeException()); | ||
} | ||
|
||
@Override | ||
public void finalizeSnapshot(FinalizeSnapshotContext finalizeSnapshotContext) { | ||
finalizeSnapshotContext.onFailure(createUnknownTypeException()); | ||
} | ||
|
||
@Override | ||
public void deleteSnapshots( | ||
Collection<SnapshotId> snapshotIds, | ||
long repositoryStateId, | ||
Version repositoryMetaVersion, | ||
ActionListener<RepositoryData> listener | ||
) { | ||
listener.onFailure(createUnknownTypeException()); | ||
} | ||
|
||
@Override | ||
public long getSnapshotThrottleTimeInNanos() { | ||
throw createUnknownTypeException(); | ||
} | ||
|
||
@Override | ||
public long getRestoreThrottleTimeInNanos() { | ||
throw createUnknownTypeException(); | ||
} | ||
|
||
@Override | ||
public String startVerification() { | ||
throw createUnknownTypeException(); | ||
} | ||
|
||
@Override | ||
public void endVerification(String verificationToken) { | ||
throw createUnknownTypeException(); | ||
} | ||
|
||
@Override | ||
public void verify(String verificationToken, DiscoveryNode localNode) { | ||
throw createUnknownTypeException(); | ||
} | ||
|
||
@Override | ||
public boolean isReadOnly() { | ||
// this repository is assumed writable to bypass read-only check and fail with exception produced by this class | ||
return false; | ||
} | ||
|
||
@Override | ||
public void snapshotShard(SnapshotShardContext snapshotShardContext) { | ||
snapshotShardContext.onFailure(createUnknownTypeException()); | ||
} | ||
|
||
@Override | ||
public void restoreShard( | ||
Store store, | ||
SnapshotId snapshotId, | ||
IndexId indexId, | ||
ShardId snapshotShardId, | ||
RecoveryState recoveryState, | ||
ActionListener<Void> listener | ||
) { | ||
listener.onFailure(createUnknownTypeException()); | ||
} | ||
|
||
@Override | ||
public IndexShardSnapshotStatus getShardSnapshotStatus(SnapshotId snapshotId, IndexId indexId, ShardId shardId) { | ||
throw createUnknownTypeException(); | ||
} | ||
|
||
@Override | ||
public void updateState(ClusterState state) { | ||
|
||
} | ||
|
||
@Override | ||
public void executeConsistentStateUpdate( | ||
Function<RepositoryData, ClusterStateUpdateTask> createUpdateTask, | ||
String source, | ||
Consumer<Exception> onFailure | ||
) { | ||
onFailure.accept(createUnknownTypeException()); | ||
} | ||
|
||
@Override | ||
public void cloneShardSnapshot( | ||
SnapshotId source, | ||
SnapshotId target, | ||
RepositoryShardId shardId, | ||
ShardGeneration shardGeneration, | ||
ActionListener<ShardSnapshotResult> listener | ||
) { | ||
listener.onFailure(createUnknownTypeException()); | ||
} | ||
|
||
@Override | ||
public void awaitIdle() { | ||
|
||
} | ||
|
||
@Override | ||
protected void doStart() { | ||
|
||
} | ||
|
||
@Override | ||
protected void doStop() { | ||
|
||
} | ||
|
||
@Override | ||
protected void doClose() throws IOException { | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
32 changes: 32 additions & 0 deletions
32
server/src/test/java/org/elasticsearch/repositories/UnknownTypeRepositoryTests.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
/* | ||
* 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.repositories; | ||
|
||
import org.elasticsearch.cluster.metadata.RepositoryMetadata; | ||
import org.elasticsearch.common.settings.Settings; | ||
import org.elasticsearch.snapshots.SnapshotId; | ||
import org.elasticsearch.test.ESTestCase; | ||
|
||
public class UnknownTypeRepositoryTests extends ESTestCase { | ||
|
||
private UnknownTypeRepository repository = new UnknownTypeRepository(new RepositoryMetadata("name", "type", Settings.EMPTY)); | ||
|
||
public void testShouldThrowWhenGettingMetadata() { | ||
expectThrows(RepositoryException.class, () -> repository.getSnapshotGlobalMetadata(new SnapshotId("name", "uuid"))); | ||
} | ||
|
||
public void testShouldNotThrowWhenApplyingLifecycleChanges() { | ||
repository.start(); | ||
repository.stop(); | ||
} | ||
|
||
public void testShouldNotThrowWhenClosingToAllowRemovingRepo() { | ||
repository.close(); | ||
} | ||
} |
Oops, something went wrong.