Do not create missing directories in readonly repo (#41249)
Today we erroneously look for a node setting called `readonly` when deciding whether or not to create a missing directory in a filesystem repository. This change fixes this by using the repository setting instead. Closes #41009 Relates #26909
This commit is contained in:
parent
3fd081528d
commit
bfa06d963e
|
@ -40,10 +40,10 @@ public class FsBlobStore implements BlobStore {
|
|||
|
||||
private final boolean readOnly;
|
||||
|
||||
public FsBlobStore(Settings settings, Path path) throws IOException {
|
||||
public FsBlobStore(Settings settings, Path path, boolean readonly) throws IOException {
|
||||
this.path = path;
|
||||
this.readOnly = settings.getAsBoolean("readonly", false);
|
||||
if (!this.readOnly) {
|
||||
this.readOnly = readonly;
|
||||
if (this.readOnly == false) {
|
||||
Files.createDirectories(path);
|
||||
}
|
||||
this.bufferSizeInBytes = (int) settings.getAsBytesSize("repositories.fs.buffer_size",
|
||||
|
@ -74,6 +74,11 @@ public class FsBlobStore implements BlobStore {
|
|||
|
||||
@Override
|
||||
public void delete(BlobPath path) throws IOException {
|
||||
assert readOnly == false : "should not delete anything from a readonly repository: " + path;
|
||||
//noinspection ConstantConditions in case assertions are disabled
|
||||
if (readOnly) {
|
||||
throw new ElasticsearchException("unexpectedly deleting [" + path + "] from a readonly repository");
|
||||
}
|
||||
IOUtils.rm(buildPath(path));
|
||||
}
|
||||
|
||||
|
@ -84,7 +89,7 @@ public class FsBlobStore implements BlobStore {
|
|||
|
||||
private synchronized Path buildAndCreate(BlobPath path) throws IOException {
|
||||
Path f = buildPath(path);
|
||||
if (!readOnly) {
|
||||
if (readOnly == false) {
|
||||
Files.createDirectories(f);
|
||||
}
|
||||
return f;
|
||||
|
|
|
@ -115,7 +115,7 @@ public class FsRepository extends BlobStoreRepository {
|
|||
protected BlobStore createBlobStore() throws Exception {
|
||||
final String location = REPOSITORIES_LOCATION_SETTING.get(metadata.settings());
|
||||
final Path locationFile = environment.resolveRepoFile(location);
|
||||
return new FsBlobStore(environment.settings(), locationFile);
|
||||
return new FsBlobStore(environment.settings(), locationFile, isReadOnly());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -37,6 +37,6 @@ public class FsBlobStoreContainerTests extends ESBlobStoreContainerTestCase {
|
|||
} else {
|
||||
settings = Settings.EMPTY;
|
||||
}
|
||||
return new FsBlobStore(settings, createTempDir());
|
||||
return new FsBlobStore(settings, createTempDir(), false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,15 +42,14 @@ public class FsBlobStoreTests extends ESBlobStoreTestCase {
|
|||
} else {
|
||||
settings = Settings.EMPTY;
|
||||
}
|
||||
return new FsBlobStore(settings, createTempDir());
|
||||
return new FsBlobStore(settings, createTempDir(), false);
|
||||
}
|
||||
|
||||
public void testReadOnly() throws Exception {
|
||||
Settings settings = Settings.builder().put("readonly", true).build();
|
||||
Path tempDir = createTempDir();
|
||||
Path path = tempDir.resolve("bar");
|
||||
|
||||
try (FsBlobStore store = new FsBlobStore(settings, path)) {
|
||||
try (FsBlobStore store = new FsBlobStore(Settings.EMPTY, path, true)) {
|
||||
assertFalse(Files.exists(path));
|
||||
BlobPath blobPath = BlobPath.cleanPath().add("foo");
|
||||
store.blobContainer(blobPath);
|
||||
|
@ -61,8 +60,7 @@ public class FsBlobStoreTests extends ESBlobStoreTestCase {
|
|||
assertFalse(Files.exists(storePath));
|
||||
}
|
||||
|
||||
settings = randomBoolean() ? Settings.EMPTY : Settings.builder().put("readonly", false).build();
|
||||
try (FsBlobStore store = new FsBlobStore(settings, path)) {
|
||||
try (FsBlobStore store = new FsBlobStore(Settings.EMPTY, path, false)) {
|
||||
assertTrue(Files.exists(path));
|
||||
BlobPath blobPath = BlobPath.cleanPath().add("foo");
|
||||
BlobContainer container = store.blobContainer(blobPath);
|
||||
|
|
|
@ -18,12 +18,22 @@
|
|||
*/
|
||||
package org.elasticsearch.repositories.fs;
|
||||
|
||||
import org.elasticsearch.ElasticsearchException;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.common.unit.ByteSizeUnit;
|
||||
import org.elasticsearch.core.internal.io.IOUtils;
|
||||
import org.elasticsearch.repositories.Repository;
|
||||
import org.elasticsearch.repositories.blobstore.ESBlobStoreRepositoryIntegTestCase;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertAcked;
|
||||
import static org.elasticsearch.test.hamcrest.ElasticsearchAssertions.assertHitCount;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
|
||||
public class FsBlobStoreRepositoryIT extends ESBlobStoreRepositoryIntegTestCase {
|
||||
|
@ -41,4 +51,47 @@ public class FsBlobStoreRepositoryIT extends ESBlobStoreRepositoryIntegTestCase
|
|||
protected void afterCreationCheck(Repository repository) {
|
||||
assertThat(repository, instanceOf(FsRepository.class));
|
||||
}
|
||||
|
||||
public void testMissingDirectoriesNotCreatedInReadonlyRepository() throws IOException, ExecutionException, InterruptedException {
|
||||
final String repoName = randomAsciiName();
|
||||
final Path repoPath = randomRepoPath();
|
||||
|
||||
logger.info("--> creating repository {} at {}", repoName, repoPath);
|
||||
|
||||
assertAcked(client().admin().cluster().preparePutRepository(repoName).setType("fs").setSettings(Settings.builder()
|
||||
.put("location", repoPath)
|
||||
.put("compress", randomBoolean())
|
||||
.put("chunk_size", randomIntBetween(100, 1000), ByteSizeUnit.BYTES)));
|
||||
|
||||
String indexName = randomAsciiName();
|
||||
int docCount = iterations(10, 1000);
|
||||
logger.info("--> create random index {} with {} records", indexName, docCount);
|
||||
addRandomDocuments(indexName, docCount);
|
||||
assertHitCount(client().prepareSearch(indexName).setSize(0).get(), docCount);
|
||||
|
||||
final String snapshotName = randomAsciiName();
|
||||
logger.info("--> create snapshot {}:{}", repoName, snapshotName);
|
||||
assertSuccessfulSnapshot(client().admin().cluster().prepareCreateSnapshot(repoName, snapshotName)
|
||||
.setWaitForCompletion(true).setIndices(indexName));
|
||||
|
||||
assertAcked(client().admin().indices().prepareDelete(indexName));
|
||||
assertAcked(client().admin().cluster().prepareDeleteRepository(repoName));
|
||||
|
||||
final Path deletedPath;
|
||||
try (Stream<Path> contents = Files.list(repoPath.resolve("indices"))) {
|
||||
//noinspection OptionalGetWithoutIsPresent because we know there's a subdirectory
|
||||
deletedPath = contents.filter(Files::isDirectory).findAny().get();
|
||||
IOUtils.rm(deletedPath);
|
||||
}
|
||||
assertFalse(Files.exists(deletedPath));
|
||||
|
||||
assertAcked(client().admin().cluster().preparePutRepository(repoName).setType("fs").setSettings(Settings.builder()
|
||||
.put("location", repoPath).put("readonly", true)));
|
||||
|
||||
final ElasticsearchException exception = expectThrows(ElasticsearchException.class, () ->
|
||||
client().admin().cluster().prepareRestoreSnapshot(repoName, snapshotName).setWaitForCompletion(randomBoolean()).get());
|
||||
assertThat(exception.getRootCause(), instanceOf(NoSuchFileException.class));
|
||||
|
||||
assertFalse("deleted path is not recreated in readonly repository", Files.exists(deletedPath));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -238,8 +238,7 @@ public class BlobStoreFormatIT extends AbstractSnapshotIntegTestCase {
|
|||
}
|
||||
|
||||
protected BlobStore createTestBlobStore() throws IOException {
|
||||
Settings settings = Settings.builder().build();
|
||||
return new FsBlobStore(settings, randomRepoPath());
|
||||
return new FsBlobStore(Settings.EMPTY, randomRepoPath(), false);
|
||||
}
|
||||
|
||||
protected void randomCorruption(BlobContainer blobContainer, String blobName) throws IOException {
|
||||
|
|
Loading…
Reference in New Issue