Browse Source

URL repos and searchable snapshots don't mix (#69197)

Provides docs and a better error message regarding using URL
repositories with searchable snapshots.

Relates #68918
David Turner 4 years ago
parent
commit
d3e0a571eb

+ 3 - 0
docs/reference/snapshot-restore/register-repository.asciidoc

@@ -176,6 +176,9 @@ repositories.url.allowed_urls: ["http://www.example.org/root/*", "https://*.mydo
 NOTE: URLs using the `ftp`, `http`, `https`, or `jar` protocols do not need to
 be registered in the `path.repo` setting.
 
+NOTE: Read-only URL repositories do not support
+<<searchable-snapshots,searchable snapshots>>.
+
 [discrete]
 [role="xpack"]
 [testenv="basic"]

+ 5 - 0
modules/repository-url/src/main/java/org/elasticsearch/repositories/url/URLRepository.java

@@ -48,6 +48,11 @@ public class URLRepository extends BlobStoreRepository {
 
     public static final String TYPE = "url";
 
+    static {
+        //noinspection ConstantConditions
+        assert TYPE.equals(BlobStoreRepository.URL_REPOSITORY_TYPE);
+    }
+
     public static final Setting<List<String>> SUPPORTED_PROTOCOLS_SETTING =
         Setting.listSetting("repositories.url.supported_protocols", Arrays.asList("http", "https", "ftp", "file", "jar"),
             Function.identity(), Property.NodeScope);

+ 4 - 0
server/src/main/java/org/elasticsearch/repositories/blobstore/BlobStoreRepository.java

@@ -176,6 +176,10 @@ public abstract class BlobStoreRepository extends AbstractLifecycleComponent imp
 
     private static final String UPLOADED_DATA_BLOB_PREFIX = "__";
 
+    // Expose a copy of URLRepository#TYPE here too, for a better error message until https://github.com/elastic/elasticsearch/issues/68918
+    // is resolved.
+    public static final String URL_REPOSITORY_TYPE = "url";
+
     /**
      * All {@link BlobStoreRepository} implementations can be made read-only by setting this key to {@code true} in their settings.
      */

+ 21 - 0
x-pack/plugin/searchable-snapshots/qa/rest/src/test/resources/rest-api-spec/test/url_repo.yml

@@ -0,0 +1,21 @@
+---
+"Tests the error returned when using a URL repository":
+  - do:
+      snapshot.create_repository:
+        repository: repository-test
+        verify: false
+        body:
+          type: url
+          settings:
+            url: "http://127.0.0.1/bogus"
+
+  - do:
+      catch:   bad_request
+      searchable_snapshots.mount:
+        repository: repository-test
+        snapshot: snapshot
+        body:
+          index: docs
+
+  - match: { error.root_cause.0.type: "illegal_argument_exception" }
+  - match: { error.root_cause.0.reason: "Searchable snapshots are not supported on URL repositories [repository-test]" }

+ 2 - 8
x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/index/store/SearchableSnapshotDirectory.java

@@ -56,8 +56,8 @@ import org.elasticsearch.repositories.Repository;
 import org.elasticsearch.repositories.RepositoryMissingException;
 import org.elasticsearch.repositories.blobstore.BlobStoreRepository;
 import org.elasticsearch.snapshots.SnapshotId;
-import org.elasticsearch.snapshots.SourceOnlySnapshotRepository;
 import org.elasticsearch.threadpool.ThreadPool;
+import org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshots;
 import org.elasticsearch.xpack.searchablesnapshots.SearchableSnapshotsConstants;
 import org.elasticsearch.xpack.searchablesnapshots.cache.CacheService;
 import org.elasticsearch.xpack.searchablesnapshots.cache.FrozenCacheService;
@@ -620,13 +620,7 @@ public class SearchableSnapshotDirectory extends BaseDirectory {
             assert repository.getMetadata().name().equals(repositoryName) : repository.getMetadata().name() + " vs " + repositoryName;
         }
 
-        if (repository instanceof SourceOnlySnapshotRepository) {
-            repository = ((SourceOnlySnapshotRepository) repository).getDelegate();
-        }
-        if (repository instanceof BlobStoreRepository == false) {
-            throw new IllegalArgumentException("Repository [" + repository + "] is not searchable");
-        }
-        final BlobStoreRepository blobStoreRepository = (BlobStoreRepository) repository;
+        final BlobStoreRepository blobStoreRepository = SearchableSnapshots.getSearchableRepository(repository);
 
         final IndexId indexId = new IndexId(
             SNAPSHOT_INDEX_NAME_SETTING.get(indexSettings.getSettings()),

+ 17 - 0
x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/SearchableSnapshots.java

@@ -54,6 +54,8 @@ import org.elasticsearch.plugins.IndexStorePlugin;
 import org.elasticsearch.plugins.Plugin;
 import org.elasticsearch.plugins.SystemIndexPlugin;
 import org.elasticsearch.repositories.RepositoriesService;
+import org.elasticsearch.repositories.Repository;
+import org.elasticsearch.repositories.blobstore.BlobStoreRepository;
 import org.elasticsearch.rest.RestController;
 import org.elasticsearch.rest.RestHandler;
 import org.elasticsearch.script.ScriptService;
@@ -230,6 +232,21 @@ public class SearchableSnapshots extends Plugin implements IndexStorePlugin, Eng
         }
     }
 
+    public static BlobStoreRepository getSearchableRepository(Repository repository) {
+        if (repository instanceof SourceOnlySnapshotRepository) {
+            repository = ((SourceOnlySnapshotRepository) repository).getDelegate();
+        }
+        if (repository instanceof BlobStoreRepository == false) {
+            throw new IllegalArgumentException("Repository [" + repository + "] is not searchable");
+        }
+        if (repository.getMetadata().type().equals(BlobStoreRepository.URL_REPOSITORY_TYPE)) {
+            throw new IllegalArgumentException(
+                "Searchable snapshots are not supported on URL repositories [" + repository.getMetadata().name() + "]"
+            );
+        }
+        return (BlobStoreRepository) repository;
+    }
+
     @Override
     public List<Setting<?>> getSettings() {
         return List.of(

+ 2 - 0
x-pack/plugin/searchable-snapshots/src/main/java/org/elasticsearch/xpack/searchablesnapshots/action/TransportMountSearchableSnapshotAction.java

@@ -160,6 +160,8 @@ public class TransportMountSearchableSnapshotAction extends TransportMasterNodeA
         // Retrieve IndexId and SnapshotId instances, which are then used to create a new restore
         // request, which is then sent on to the actual snapshot restore mechanism
         final Repository repository = repositoriesService.repository(repoName);
+        SearchableSnapshots.getSearchableRepository(repository); // just check it's valid
+
         final StepListener<RepositoryData> repositoryDataListener = new StepListener<>();
         repository.getRepositoryData(repositoryDataListener);
         repositoryDataListener.whenComplete(repoData -> {