From e6c35a08760b8413a53196b77c49521b83551bde Mon Sep 17 00:00:00 2001 From: Hammad Bashir Date: Tue, 30 Apr 2024 21:04:37 -0700 Subject: [PATCH] [ENH] Allow config of storage from env (#2093) ## Description of changes *Summarize the changes made by this PR.* - Improvements & Bug fixes - Allows configuring storage credentials from ENV by allowing case insensitivity. - New functionality - None ## Test plan *How are these changes tested?* A test was modified to use env and assert the config is as expected - [x/ Tests pass locally with `pytest` for python, `yarn test` for js, `cargo test` for rust ## Documentation Changes None --- rust/worker/src/config.rs | 16 ++++++++++++---- rust/worker/src/storage/config.rs | 5 ++++- rust/worker/test.arrow | Bin 0 -> 67422 bytes 3 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 rust/worker/test.arrow diff --git a/rust/worker/src/config.rs b/rust/worker/src/config.rs index c8629e5c376..a441074f146 100644 --- a/rust/worker/src/config.rs +++ b/rust/worker/src/config.rs @@ -395,6 +395,8 @@ mod tests { let _ = jail.set_env("CHROMA_QUERY_SERVICE__MY_PORT", 50051); let _ = jail.set_env("CHROMA_COMPACTION_SERVICE__MY_IP", "192.0.0.1"); let _ = jail.set_env("CHROMA_COMPACTION_SERVICE__MY_PORT", 50051); + let _ = jail.set_env("CHROMA_COMPACTION_SERVICE__STORAGE__S3__BUCKET", "buckets!"); + let _ = jail.set_env("CHROMA_COMPACTION_SERVICE__STORAGE__S3__CREDENTIALS", "AWS"); let _ = jail.create_file( "chroma_config.yaml", r#" @@ -437,10 +439,6 @@ mod tests { Grpc: host: "localhost" port: 50051 - storage: - S3: - bucket: "chroma" - credentials: Minio log: Grpc: host: "localhost" @@ -458,6 +456,16 @@ mod tests { let config = RootConfig::load(); assert_eq!(config.query_service.my_ip, "192.0.0.1"); assert_eq!(config.query_service.my_port, 50051); + match &config.compaction_service.storage { + crate::storage::config::StorageConfig::S3(s) => { + assert_eq!(s.bucket, "buckets!"); + assert_eq!( + s.credentials, + crate::storage::config::S3CredentialsConfig::AWS + ); + } + _ => panic!("Invalid storage config"), + } Ok(()) }); } diff --git a/rust/worker/src/storage/config.rs b/rust/worker/src/storage/config.rs index ec2a058d864..b8cf4b784f0 100644 --- a/rust/worker/src/storage/config.rs +++ b/rust/worker/src/storage/config.rs @@ -9,11 +9,14 @@ use std::path::Path; /// See config.rs in the root of the worker crate for an example of how to use /// config files to configure the worker. pub(crate) enum StorageConfig { + // case-insensitive + #[serde(alias = "s3")] S3(S3StorageConfig), + #[serde(alias = "local")] Local(LocalStorageConfig), } -#[derive(Deserialize)] +#[derive(Deserialize, PartialEq, Debug)] pub(crate) enum S3CredentialsConfig { Minio, AWS, diff --git a/rust/worker/test.arrow b/rust/worker/test.arrow new file mode 100644 index 0000000000000000000000000000000000000000..3f01356b51521af8cb6b6e09c27b0d392c7e59d2 GIT binary patch literal 67422 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 X_3wkn_xFA%_qDGdKYsk_=O4ZS8d%$r literal 0 HcmV?d00001