Add S3 bucket configuration

This commit is contained in:
2023-08-05 14:49:17 +02:00
parent aa351bfae9
commit 4cd7519890
6 changed files with 400 additions and 8 deletions

View File

@ -1,4 +1,6 @@
use clap::Parser;
use s3::creds::Credentials;
use s3::{Bucket, Region};
/// GeneIT backend API
#[derive(Parser, Debug, Clone)]
@ -115,6 +117,30 @@ pub struct AppConfig {
/// OpenID login redirect URL
#[arg(long, env, default_value = "APP_ORIGIN/oidc_cb")]
oidc_redirect_url: String,
/// S3 Bucket name
#[arg(long, env, default_value = "geneit-data")]
s3_bucket_name: String,
/// S3 region (if not using Minio)
#[arg(long, env, default_value = "eu-central-1")]
s3_region: String,
/// S3 API endpoint
#[arg(long, env, default_value = "http://localhost:9000")]
s3_endpoint: String,
/// S3 access key
#[arg(long, env, default_value = "topsecret")]
s3_access_key: String,
/// S3 secret key
#[arg(long, env, default_value = "topsecret")]
s3_secret_key: String,
/// S3 skip auto create bucket if not existing
#[arg(long, env)]
pub s3_skip_auto_create_bucket: bool,
}
lazy_static::lazy_static! {
@ -183,6 +209,30 @@ impl AppConfig {
self.oidc_redirect_url
.replace("APP_ORIGIN", &self.website_origin)
}
/// Get s3 credentials
pub fn s3_credentials(&self) -> anyhow::Result<Credentials> {
Ok(Credentials::new(
Some(&self.s3_access_key),
Some(&self.s3_secret_key),
None,
None,
None,
)?)
}
/// Get S3 bucket
pub fn s3_bucket(&self) -> anyhow::Result<Bucket> {
Ok(Bucket::new(
&self.s3_bucket_name,
Region::Custom {
region: self.s3_region.to_string(),
endpoint: self.s3_endpoint.to_string(),
},
self.s3_credentials()?,
)?
.with_path_style())
}
}
#[derive(Debug, Clone, serde::Serialize)]

View File

@ -2,3 +2,4 @@
pub mod db_connection;
pub mod redis_connection;
pub mod s3_connection;

View File

@ -0,0 +1,47 @@
use crate::app_config::AppConfig;
use s3::error::S3Error;
use s3::{Bucket, BucketConfiguration};
#[derive(thiserror::Error, Debug)]
enum BucketServiceError {
#[error("Failed to fetch bucket information!")]
FailedFetchBucketInfo,
}
/// Create S3 bucket if required
pub async fn create_bucket_if_required() -> anyhow::Result<()> {
if AppConfig::get().s3_skip_auto_create_bucket {
log::debug!("Skipping bucket existence check");
return Ok(());
}
let bucket = AppConfig::get().s3_bucket()?;
match bucket.location().await {
Ok(_) => {
log::debug!("The bucket already exists.");
return Ok(());
}
Err(S3Error::Http(404, s)) if s.contains("<Code>NoSuchKey</Code>") => {
log::warn!("Failed to fetch bucket location, but it seems that bucket exists.");
return Ok(());
}
Err(S3Error::Http(404, s)) if s.contains("<Code>NoSuchBucket</Code>") => {
log::warn!("The bucket does not seem to exists, trying to create it!")
}
Err(e) => {
log::error!("Got unexpected error when querying bucket info: {}", e);
return Err(BucketServiceError::FailedFetchBucketInfo.into());
}
}
Bucket::create_with_path_style(
&bucket.name,
bucket.region,
AppConfig::get().s3_credentials()?,
BucketConfiguration::private(),
)
.await?;
Ok(())
}

View File

@ -3,6 +3,7 @@ use actix_remote_ip::RemoteIPConfig;
use actix_web::middleware::Logger;
use actix_web::{web, App, HttpServer};
use geneit_backend::app_config::AppConfig;
use geneit_backend::connections::s3_connection;
use geneit_backend::controllers::{
auth_controller, families_controller, members_controller, server_controller, users_controller,
};
@ -13,6 +14,12 @@ async fn main() -> std::io::Result<()> {
log::info!("Start to listen on {}", AppConfig::get().listen_address);
// Initialize bucket
log::info!("Initialize bucket");
s3_connection::create_bucket_if_required()
.await
.expect("Failed to initialize S3 bucket!");
HttpServer::new(|| {
App::new()
.wrap(