Skip to content

Commit 66a1418

Browse files
fulmicotonguilload
andauthored
Adds support for custom s3 endpoint. (#1093)
* Adds support for custom s3 endpoint. This removes our trickery to use localstack, and replaces it by a way to set a specific endpoint via an environment variable: `QW_S3_REGION`. Closes #49 Closes #1037 Co-authored-by: Adrien Guillo <[email protected]>
1 parent a757843 commit 66a1418

File tree

16 files changed

+171
-215
lines changed

16 files changed

+171
-215
lines changed

.github/workflows/coverage.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ on:
1212
- "quickwit-*/**"
1313

1414
env:
15+
QW_S3_ENDPOINT: "http://localstack:4566"
1516
AWS_DEFAULT_REGION : "localhost"
1617
AWS_ACCESS_KEY_ID : "placeholder"
1718
AWS_SECRET_ACCESS_KEY: "placeholder"

CONTRIBUTING.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ The process is simple and fast. Upon your first pull request, you will be prompt
2828
1. Install Docker (https://docs.docker.com/engine/install/) and Docker Compose (https://docs.docker.com/compose/install/)
2929
2. Install awslocal https://github.com/localstack/awscli-local
3030
3. Start the external services with `make docker-compose-up`
31-
5. Run `QW_ENV=LOCAL cargo test --all-features`
31+
5. Run `QW_S3_ENDPOINT=http://localhost:4566 cargo test --all-features`
3232

3333
## Running services such as Amazon Kinesis or S3, Kafka, or PostgreSQL locally.
3434
1. Ensure Docker and Docker Compose are correctly installed on your machine (see above)
@@ -48,8 +48,8 @@ The process is simple and fast. Upon your first pull request, you will be prompt
4848
## Building binaries
4949

5050
Currently, we use [cross](https://github.com/rust-embedded/cross) to build Quickwit binaries for different architectures.
51-
For this to work, we've had to customize the docker images cross uses. These customizations can be found in docker files located in `./cross-images` folder. To make cross take into account any change on those
52-
docker files, you will need to build and push the images on dockerhub by running `make cross-images`.
51+
For this to work, we've had to customize the docker images cross uses. These customizations can be found in docker files located in `./cross-images` folder. To make cross take into account any change on those
52+
docker files, you will need to build and push the images on dockerhub by running `make cross-images`.
5353
We also have nightly builds that are pushed to dockerhub. This helps continiously check our binaries are still built even with external dependency update. Successful builds let you accessed the artifacts for the next three days. Release builds always have their artifacts attached to the release.
5454

5555
## Testing release (alpha, beta, rc)

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fmt:
3030
# `make test-all` starts the Docker services and runs all the tests.
3131
# `make -k test-all docker-compose-down`, tears down the Docker services after running all the tests.
3232
test-all: docker-compose-up
33-
QW_ENV=local AWS_ACCESS_KEY_ID=ignored AWS_SECRET_ACCESS_KEY=ignored cargo test --all-features
33+
QW_S3_ENDPOINT=http://localhost:4566 AWS_ACCESS_KEY_ID=ignored AWS_SECRET_ACCESS_KEY=ignored cargo test --all-features
3434

3535
# This will build and push all custom cross images for cross-compilation.
3636
# You will need to login into Docker Hub with the `quickwit` account.
@@ -59,7 +59,7 @@ build:
5959
esac
6060

6161
# Usage:
62-
# `BINARY_FILE=path/to/quickwit/binary BINARY_VERSION=0.1.0 ARCHIVE_NAME=quickwit make archive`
62+
# `BINARY_FILE=path/to/quickwit/binary BINARY_VERSION=0.1.0 ARCHIVE_NAME=quickwit make archive`
6363
# - BINARY_FILE: Path of the quickwit binary file.
6464
# - BINARY_VERSION: Version of the quickwit binary.
6565
# - ARCHIVE_NAME: Name of the resulting archive file (without extension).

docs/reference/storage-uri.md

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ In Quickwit, Storage URIs refer to different kinds of storage.
77

88
Generally speaking, you can use a storage URI or a regular file path wherever you would have expected a file path.
99

10-
10+
1111
For instance
1212

1313
- when configuring the index storage. (Passed as the `index_uri` in the index command line.)
@@ -26,7 +26,7 @@ The following are valid local file system URIs
2626
- /var/quickwit
2727
- file:///var/quickwit
2828
- /home/quickwit/data
29-
- ~/data
29+
- ~/data
3030
- ./quickwit
3131
```
3232

@@ -64,13 +64,20 @@ Quickwit will detect the S3 credentials using the first successful method in thi
6464

6565
### Region
6666

67-
The region will be detected using the first successful method in this list (order matters)
68-
67+
The region or custom endpoint will be detected using the first successful method in this list (order matters)
6968
- `AWS_DEFAULT_REGION` environment variable
7069
- `AWS_REGION` environment variable
7170
- Amazon’s instance metadata API [https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html)
7271

73-
:::caution
74-
Custom endpoints are not supported yet.
72+
### S3-compatible Objective storage like Minio
7573

76-
:::
74+
75+
Quickwit can target other S3-compatible storage like MinIO.
76+
This is done by setting an endpoint url in the `QW_S3_ENDPOINT` environment variable.
77+
78+
In this case, the region will be ignored.
79+
80+
For instance:
81+
```bash
82+
export QW_S3_ENDPOINT=http://localhost:9000/
83+
```

quickwit-cli/tests/cli.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -709,7 +709,7 @@ async fn test_all_local_index() -> Result<()> {
709709
#[tokio::test]
710710
#[serial]
711711
#[cfg_attr(not(feature = "ci-test"), ignore)]
712-
async fn test_all_with_s3_localstack_cli() -> Result<()> {
712+
async fn test_cmd_all_with_s3_localstack_cli() -> Result<()> {
713713
let index_id = append_random_suffix("test-all--cli-s3-localstack");
714714
let test_env = create_test_env(index_id, TestStorageType::S3)?;
715715
make_command(
@@ -723,11 +723,11 @@ async fn test_all_with_s3_localstack_cli() -> Result<()> {
723723
.assert()
724724
.success();
725725

726-
let index_metadata = test_env
726+
test_env
727727
.metastore()
728728
.index_metadata(&test_env.index_id)
729-
.await;
730-
assert_eq!(index_metadata.is_ok(), true);
729+
.await
730+
.unwrap();
731731

732732
ingest_docs(test_env.resource_files["logs"].as_path(), &test_env);
733733

@@ -797,7 +797,7 @@ async fn test_all_with_s3_localstack_cli() -> Result<()> {
797797
#[tokio::test]
798798
#[serial]
799799
#[cfg_attr(not(feature = "ci-test"), ignore)]
800-
async fn test_all_with_s3_localstack_internal_api() -> Result<()> {
800+
async fn test_cmd_all_with_s3_localstack_internal_api() -> Result<()> {
801801
let index_id = append_random_suffix("test-all--cli-API");
802802
let test_env = create_test_env(index_id, TestStorageType::S3)?;
803803
let args = CreateIndexArgs {

quickwit-cli/tests/helpers.rs

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ use predicates::str;
2929
use quickwit_common::net::find_available_port;
3030
use quickwit_common::uri::Uri;
3131
use quickwit_metastore::FileBackedMetastore;
32-
use quickwit_storage::{LocalFileStorage, RegionProvider, S3CompatibleObjectStorage, Storage};
32+
use quickwit_storage::{LocalFileStorage, S3CompatibleObjectStorage, Storage};
3333
use tempfile::{tempdir, TempDir};
3434

3535
const PACKAGE_BIN_NAME: &str = "quickwit";
@@ -90,16 +90,13 @@ const WIKI_JSON_DOCS: &str = r#"{"body": "foo", "title": "shimroy", "url": "http
9090
{"body": "biz", "title": "modern", "url": "https://wiki.com?id=13"}
9191
"#;
9292

93-
const AWS_DEFAULT_REGION_ENV: &str = "AWS_DEFAULT_REGION";
94-
9593
/// Creates a quickwit-cli command with provided list of arguments.
9694
pub fn make_command(arguments: &str) -> Command {
9795
let mut cmd = Command::cargo_bin(PACKAGE_BIN_NAME).unwrap();
9896
cmd.env(
9997
quickwit_telemetry::DISABLE_TELEMETRY_ENV_KEY,
10098
"disable-for-tests",
10199
)
102-
.env(AWS_DEFAULT_REGION_ENV, "us-east-1")
103100
.args(arguments.split_whitespace());
104101
cmd
105102
}
@@ -110,7 +107,6 @@ pub fn make_command_with_list_of_args(arguments: &[&str]) -> Command {
110107
quickwit_telemetry::DISABLE_TELEMETRY_ENV_KEY,
111108
"disable-for-tests",
112109
)
113-
.env(AWS_DEFAULT_REGION_ENV, "us-east-1")
114110
.args(arguments.iter());
115111
cmd
116112
}
@@ -123,8 +119,6 @@ pub fn spawn_command(arguments: &str) -> io::Result<Child> {
123119
quickwit_telemetry::DISABLE_TELEMETRY_ENV_KEY,
124120
"disable-for-tests",
125121
)
126-
.env(AWS_DEFAULT_REGION_ENV, "us-east-1")
127-
.stdout(Stdio::piped())
128122
.stdout(Stdio::piped())
129123
.spawn()
130124
}
@@ -179,15 +173,13 @@ pub fn create_test_env(index_id: String, storage_type: TestStorageType) -> anyho
179173
(metastore_uri, storage)
180174
}
181175
TestStorageType::S3 => {
182-
let metastore_uri = "s3+localstack://quickwit-integration-tests/indexes";
183-
let storage: Arc<dyn Storage> = Arc::new(S3CompatibleObjectStorage::from_uri(
184-
RegionProvider::Localstack.get_region(),
185-
metastore_uri,
186-
)?);
176+
let metastore_uri = "s3://quickwit-integration-tests/indexes";
177+
let storage: Arc<dyn Storage> =
178+
Arc::new(S3CompatibleObjectStorage::from_uri(metastore_uri)?);
187179
(metastore_uri.to_string(), storage)
188180
}
189181
};
190-
let index_uri = Uri::try_new(&format!("{}/{}", metastore_uri, index_id))?;
182+
let index_uri = Uri::try_new(&format!("{metastore_uri}/{index_id}"))?;
191183
let index_config_path = resources_dir_path.join("index_config.yaml");
192184
fs::write(
193185
&index_config_path,

quickwit-common/src/lib.rs

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -33,26 +33,6 @@ pub use checklist::{print_checklist, run_checklist, BLUE_COLOR, GREEN_COLOR, RED
3333
pub use coolid::new_coolid;
3434
use tracing::{error, info};
3535

36-
#[derive(Debug, PartialEq, Eq)]
37-
pub enum QuickwitEnv {
38-
UNSET,
39-
LOCAL,
40-
}
41-
42-
impl Default for QuickwitEnv {
43-
fn default() -> Self {
44-
Self::UNSET
45-
}
46-
}
47-
48-
pub fn get_quickwit_env() -> QuickwitEnv {
49-
match std::env::var("QW_ENV") {
50-
Ok(val) if val.to_lowercase().trim() == "local" => QuickwitEnv::LOCAL,
51-
Ok(val) => panic!("QW_ENV value `{}` is not supported", val),
52-
Err(_) => QuickwitEnv::UNSET,
53-
}
54-
}
55-
5636
pub fn chunk_range(range: Range<usize>, chunk_size: usize) -> impl Iterator<Item = Range<usize>> {
5737
range.clone().step_by(chunk_size).map(move |block_start| {
5838
let block_end = (block_start + chunk_size).min(range.end);

quickwit-metastore/src/metastore_resolver.rs

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -71,12 +71,12 @@ pub fn quickwit_metastore_uri_resolver() -> &'static MetastoreUriResolver {
7171
let mut builder = MetastoreUriResolver::builder()
7272
.register("ram", FileBackedMetastoreFactory::default())
7373
.register("file", FileBackedMetastoreFactory::default())
74-
.register("s3", FileBackedMetastoreFactory::default())
75-
.register("s3+localstack", FileBackedMetastoreFactory::default());
74+
.register("s3", FileBackedMetastoreFactory::default());
7675
#[cfg(feature = "postgres")]
7776
{
78-
builder = builder.register("postgres", PostgresqlMetastoreFactory::default());
79-
builder = builder.register("postgresql", PostgresqlMetastoreFactory::default());
77+
builder = builder
78+
.register("postgres", PostgresqlMetastoreFactory::default())
79+
.register("postgresql", PostgresqlMetastoreFactory::default());
8080
}
8181

8282
builder.build()
@@ -113,13 +113,9 @@ mod tests {
113113
use crate::quickwit_metastore_uri_resolver;
114114

115115
#[tokio::test]
116-
async fn test_metastore_resolver_should_not_raise_errors_on_file_and_s3() -> anyhow::Result<()>
117-
{
116+
async fn test_metastore_resolver_should_not_raise_errors_on_file() -> anyhow::Result<()> {
118117
let metastore_resolver = quickwit_metastore_uri_resolver();
119118
metastore_resolver.resolve("file://").await?;
120-
metastore_resolver
121-
.resolve("s3://bucket/path/to/object")
122-
.await?;
123119
Ok(())
124120
}
125121

quickwit-serve/src/lib.rs

Lines changed: 2 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ use quickwit_cluster::service::ClusterServiceImpl;
3232
use quickwit_config::{QuickwitConfig, SEARCHER_CONFIG_INSTANCE};
3333
use quickwit_metastore::Metastore;
3434
use quickwit_search::{ClusterClient, SearchClientPool, SearchServiceImpl};
35-
use quickwit_storage::{
36-
LocalFileStorageFactory, RegionProvider, S3CompatibleObjectStorageFactory, StorageUriResolver,
37-
};
35+
use quickwit_storage::quickwit_storage_uri_resolver;
3836
use tracing::{debug, info};
3937

4038
pub use crate::args::ServeArgs;
@@ -45,22 +43,6 @@ use crate::grpc_adapter::cluster_adapter::GrpcClusterAdapter;
4543
use crate::grpc_adapter::search_adapter::GrpcSearchAdapter;
4644
use crate::rest::start_rest_service;
4745

48-
/// Builds a storage uri resolver that handles
49-
/// - s3:// uris. This storage comes with a cache that stores hotcache files.
50-
/// - s3+localstack://
51-
/// - file:// uris.
52-
fn storage_uri_resolver() -> StorageUriResolver {
53-
let s3_storage = S3CompatibleObjectStorageFactory::default();
54-
StorageUriResolver::builder()
55-
.register(LocalFileStorageFactory::default())
56-
.register(s3_storage)
57-
.register(S3CompatibleObjectStorageFactory::new(
58-
RegionProvider::Localstack,
59-
"s3+localstack",
60-
))
61-
.build()
62-
}
63-
6446
/// Starts a search node, aka a `searcher`.
6547
pub async fn run_searcher(
6648
quickwit_config: QuickwitConfig,
@@ -79,7 +61,7 @@ pub async fn run_searcher(
7961
debug!(peer_seed_addr = %seed_socket_addr, "Add peer seed node.");
8062
cluster.add_peer_node(seed_socket_addr).await;
8163
}
82-
let storage_uri_resolver = storage_uri_resolver();
64+
let storage_uri_resolver = quickwit_storage_uri_resolver().clone();
8365
let client_pool = Arc::new(SearchClientPool::new(cluster.clone()).await?);
8466
let cluster_client = ClusterClient::new(client_pool.clone());
8567
let search_service = Arc::new(SearchServiceImpl::new(

quickwit-storage/src/error.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub enum StorageErrorKind {
3030
DoesNotExist,
3131
/// The request credentials do not allow for this operation.
3232
Unauthorized,
33-
/// A third-party service forbids this operation.
33+
/// A third-party service forbids this operation, or is misconfigured.
3434
Service,
3535
/// Any generic internal error.
3636
InternalError,

0 commit comments

Comments
 (0)