Create a cold storage client. Connects to the configured S3-compatible endpoint, or uses local filesystem if no endpoint is configured.
(config: ColdStorageConfig)
| 114 | /// Connects to the configured S3-compatible endpoint, or uses |
| 115 | /// local filesystem if no endpoint is configured. |
| 116 | pub fn new(config: ColdStorageConfig) -> crate::Result<Self> { |
| 117 | let store: Arc<dyn ObjectStore> = if config.endpoint.is_empty() { |
| 118 | // Local filesystem (dev/testing). |
| 119 | let dir = config |
| 120 | .local_dir |
| 121 | .clone() |
| 122 | .unwrap_or_else(|| PathBuf::from("/tmp/nodedb/cold")); |
| 123 | std::fs::create_dir_all(&dir)?; |
| 124 | Arc::new(LocalFileSystem::new_with_prefix(&dir).map_err(|e| { |
| 125 | crate::Error::ColdStorage { |
| 126 | detail: format!("local cold storage: {e}"), |
| 127 | } |
| 128 | })?) |
| 129 | } else { |
| 130 | // S3-compatible object store. |
| 131 | let mut builder = AmazonS3Builder::new() |
| 132 | .with_endpoint(&config.endpoint) |
| 133 | .with_bucket_name(&config.bucket) |
| 134 | .with_region(&config.region) |
| 135 | .with_allow_http(config.endpoint.starts_with("http://")); |
| 136 | |
| 137 | if !config.access_key.is_empty() { |
| 138 | builder = builder |
| 139 | .with_access_key_id(&config.access_key) |
| 140 | .with_secret_access_key(&config.secret_key); |
| 141 | } |
| 142 | |
| 143 | match &config.sse_mode { |
| 144 | Some(SseMode::Aes256) => { |
| 145 | // AES256 = SSE-S3 (S3-managed keys). |
| 146 | // object_store 0.13 configures SSE-S3 via the "server_side_encryption" |
| 147 | // config key with value "AES256". This maps to |
| 148 | // `S3EncryptionType::S3` → `x-amz-server-side-encryption: AES256`. |
| 149 | use object_store::aws::AmazonS3ConfigKey; |
| 150 | let sse_key = "server_side_encryption" |
| 151 | .parse::<AmazonS3ConfigKey>() |
| 152 | .map_err(|e| crate::Error::ColdStorage { |
| 153 | detail: format!( |
| 154 | "SSE-S3 config key parse error (object_store version mismatch?): {e}" |
| 155 | ), |
| 156 | })?; |
| 157 | builder = builder.with_config(sse_key, "AES256"); |
| 158 | } |
| 159 | Some(SseMode::Kms { key_id }) => { |
| 160 | let id = key_id.as_deref().unwrap_or(""); |
| 161 | builder = builder.with_sse_kms_encryption(id); |
| 162 | } |
| 163 | None => {} |
| 164 | } |
| 165 | |
| 166 | let s3 = builder.build().map_err(|e| crate::Error::ColdStorage { |
| 167 | detail: format!("S3 client init: {e}"), |
| 168 | })?; |
| 169 | Arc::new(s3) |
| 170 | }; |
| 171 | |
| 172 | Ok(Self { |
| 173 | config, |
nothing calls this directly
no test coverage detected