Skip to content

Commit 0866591

Browse files
committed
Improve get-snapshots message for unreadable repository
Today if the get-snapshots API cannot access one of the repositories we return a fairly low-level message about the problem, perhaps something like `Could not determine repository generation from root blobs`. This message is shown verbatim in the Kibana UI so users need something a little more descriptive. With this commit we wrap the exception in one that indicates the problem in terms that users are more likely to understand. Relates #128208
1 parent 79d3aa8 commit 0866591

File tree

2 files changed

+61
-1
lines changed

2 files changed

+61
-1
lines changed

server/src/internalClusterTest/java/org/elasticsearch/snapshots/GetSnapshotsIT.java

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@
4040
import org.elasticsearch.core.Predicates;
4141
import org.elasticsearch.repositories.RepositoriesService;
4242
import org.elasticsearch.repositories.RepositoryData;
43+
import org.elasticsearch.repositories.RepositoryException;
4344
import org.elasticsearch.repositories.RepositoryMissingException;
45+
import org.elasticsearch.repositories.blobstore.BlobStoreRepository;
4446
import org.elasticsearch.repositories.fs.FsRepository;
4547
import org.elasticsearch.search.sort.SortOrder;
4648
import org.elasticsearch.test.ESTestCase;
@@ -633,6 +635,50 @@ public void testRetrievingSnapshotsWhenRepositoryIsMissing() throws Exception {
633635
expectThrows(RepositoryMissingException.class, multiRepoFuture::actionGet);
634636
}
635637

638+
public void testRetrievingSnapshotsWhenRepositoryIsUnreadable() throws Exception {
639+
final String repoName = randomIdentifier();
640+
final Path repoPath = randomRepoPath();
641+
createRepository(
642+
repoName,
643+
"fs",
644+
Settings.builder().put("location", repoPath).put(BlobStoreRepository.CACHE_REPOSITORY_DATA.getKey(), false)
645+
);
646+
createNSnapshots(repoName, randomIntBetween(1, 3));
647+
648+
try {
649+
try (var directoryStream = Files.newDirectoryStream(repoPath)) {
650+
for (final var directoryEntry : directoryStream) {
651+
if (Files.isRegularFile(directoryEntry) && directoryEntry.getFileName().toString().startsWith("index-")) {
652+
Files.writeString(directoryEntry, "invalid");
653+
}
654+
}
655+
}
656+
657+
final var repositoryException = asInstanceOf(
658+
RepositoryException.class,
659+
safeAwaitFailure(
660+
GetSnapshotsResponse.class,
661+
l -> clusterAdmin().prepareGetSnapshots(TEST_REQUEST_TIMEOUT, repoName)
662+
.setSort(SnapshotSortKey.NAME)
663+
.setIgnoreUnavailable(randomBoolean())
664+
.execute(l)
665+
)
666+
);
667+
assertEquals(
668+
Strings.format("[%s] cannot retrieve snapshots list from this repository", repoName),
669+
repositoryException.getMessage()
670+
);
671+
assertEquals(
672+
Strings.format("[%s] Unexpected exception when loading repository data", repoName),
673+
repositoryException.getCause().getMessage()
674+
);
675+
} finally {
676+
safeAwait(
677+
l -> clusterAdmin().prepareDeleteRepository(TEST_REQUEST_TIMEOUT, TEST_REQUEST_TIMEOUT, repoName).execute(l.map(v -> null))
678+
);
679+
}
680+
}
681+
636682
// Create a snapshot that is guaranteed to have a unique start time and duration for tests around ordering by either.
637683
// Don't use this with more than 3 snapshots on platforms with low-resolution clocks as the durations could always collide there
638684
// causing an infinite loop

server/src/main/java/org/elasticsearch/action/admin/cluster/snapshots/get/TransportGetSnapshotsAction.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import org.elasticsearch.repositories.RepositoriesService;
3939
import org.elasticsearch.repositories.Repository;
4040
import org.elasticsearch.repositories.RepositoryData;
41+
import org.elasticsearch.repositories.RepositoryException;
4142
import org.elasticsearch.repositories.RepositoryMissingException;
4243
import org.elasticsearch.repositories.ResolvedRepositories;
4344
import org.elasticsearch.search.sort.SortOrder;
@@ -285,7 +286,20 @@ private void populateResults(ActionListener<Void> listener) {
285286
),
286287
repositoryName -> asyncRepositoryContentsListener -> SubscribableListener
287288

288-
.<RepositoryData>newForked(l -> maybeGetRepositoryData(repositoryName, l))
289+
.<RepositoryData>newForked(
290+
l -> maybeGetRepositoryData(
291+
repositoryName,
292+
l.delegateResponse(
293+
(ll, e) -> ll.onFailure(
294+
new RepositoryException(
295+
repositoryName,
296+
"cannot retrieve snapshots list from this repository",
297+
e
298+
)
299+
)
300+
)
301+
)
302+
)
289303
.andThenApply(repositoryData -> {
290304
assert ThreadPool.assertCurrentThreadPool(ThreadPool.Names.MANAGEMENT);
291305
cancellableTask.ensureNotCancelled();

0 commit comments

Comments
 (0)