diff --git a/services/blob/Dockerfile b/services/blob/Dockerfile index d0e2facb9..fe2d08da5 100644 --- a/services/blob/Dockerfile +++ b/services/blob/Dockerfile @@ -1,42 +1,42 @@ FROM rust:1.70-bullseye as builder RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ build-essential cmake git libgtest-dev libssl-dev zlib1g-dev \ && rm -rf /var/lib/apt/lists/* WORKDIR /home/root/app/blob # Install more recent version of protobuf, must be ran as root COPY scripts/install_protobuf.sh ../../scripts/install_protobuf.sh RUN ../../scripts/install_protobuf.sh ENV CARGO_REGISTRIES_CRATES_IO_PROTOCOL=sparse # Copy actual application sources COPY shared ../../shared/ COPY services/comm-services-lib ../comm-services-lib COPY services/blob ./ RUN cargo install --locked --path . # Runner stage FROM debian:bullseye-slim as runner # Update dependencies, install ca-certificates which are required for TLS RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \ ca-certificates \ && rm -rf /var/lib/apt/lists/* # Only copy built binary from builder stage COPY --from=builder /usr/local/cargo/bin/blob /usr/local/bin/blob WORKDIR /home/comm/app/blob # Create a new user comm and use it to run subsequent commands RUN useradd -m comm USER comm ENV RUST_LOG=info -CMD ["blob"] +CMD ["blob", "server"] diff --git a/services/blob/src/config.rs b/services/blob/src/config.rs index 3899c1174..a11e6316f 100644 --- a/services/blob/src/config.rs +++ b/services/blob/src/config.rs @@ -1,55 +1,64 @@ use anyhow::Result; use clap::Parser; use once_cell::sync::Lazy; use tracing::info; use crate::constants::{ DEFAULT_HTTP_PORT, DEFAULT_S3_BUCKET_NAME, S3_BUCKET_ENV_VAR, }; #[derive(Parser)] #[command(version, about, long_about = None)] pub struct AppConfig { /// HTTP server listening port - #[arg(long, default_value_t = DEFAULT_HTTP_PORT)] + #[arg(long, default_value_t = DEFAULT_HTTP_PORT, global = true)] pub http_port: u16, /// AWS Localstack service URL #[arg(env = "LOCALSTACK_ENDPOINT")] #[arg(long)] pub localstack_endpoint: Option, #[arg(env = S3_BUCKET_ENV_VAR)] #[arg(long, default_value_t = DEFAULT_S3_BUCKET_NAME.to_string())] pub s3_bucket_name: String, /// Identity service endpoint #[arg(env = "IDENTITY_SERVICE_ENDPOINT")] #[arg(long, default_value = "http://localhost:50054")] pub identity_endpoint: String, + + #[clap(subcommand)] + pub command: Option, +} + +#[derive(clap::Subcommand)] +pub enum Command { + Server, + Cleanup, } /// Stores configuration parsed from command-line arguments /// and environment variables pub static CONFIG: Lazy = Lazy::new(AppConfig::parse); /// Processes the command-line arguments and environment variables. /// Should be called at the beginning of the `main()` function. pub(super) fn parse_cmdline_args() -> Result<&'static AppConfig> { // force evaluation of the lazy initialized config let cfg = Lazy::force(&CONFIG); if cfg.s3_bucket_name != DEFAULT_S3_BUCKET_NAME { info!("Using custom S3 bucket: {}", &cfg.s3_bucket_name); } Ok(cfg) } /// Provides region/credentials configuration for AWS SDKs pub async fn load_aws_config() -> aws_config::SdkConfig { let mut config_builder = aws_config::from_env(); if let Some(endpoint) = &CONFIG.localstack_endpoint { info!("Using Localstack. AWS endpoint URL: {}", endpoint); config_builder = config_builder.endpoint_url(endpoint); } config_builder.load().await } diff --git a/services/blob/src/main.rs b/services/blob/src/main.rs index 2f01c0e0a..13bef2ae2 100644 --- a/services/blob/src/main.rs +++ b/services/blob/src/main.rs @@ -1,46 +1,48 @@ pub mod config; pub mod constants; pub mod database; pub mod http; pub mod s3; pub mod service; pub mod tools; use anyhow::Result; use comm_services_lib::auth::AuthService; +use config::Command; use tracing_subscriber::filter::{EnvFilter, LevelFilter}; use crate::service::BlobServiceConfig; fn configure_logging() -> Result<()> { let filter = EnvFilter::builder() .with_default_directive(LevelFilter::INFO.into()) .with_env_var(constants::LOG_LEVEL_ENV_VAR) .from_env_lossy(); let subscriber = tracing_subscriber::fmt().with_env_filter(filter).finish(); tracing::subscriber::set_global_default(subscriber)?; Ok(()) } #[tokio::main] async fn main() -> Result<()> { configure_logging()?; let config = config::parse_cmdline_args()?; let aws_config = config::load_aws_config().await; let db = database::DatabaseClient::new(&aws_config); let s3 = s3::S3Client::new(&aws_config); let auth_service = AuthService::new(&aws_config, &config.identity_endpoint); - let blob_service = service::BlobService::new( - db, - s3, - BlobServiceConfig { - instant_delete_orphaned_blobs: true, - ..Default::default() - }, - ); + let blob_service = + service::BlobService::new(db, s3, BlobServiceConfig::default()); - crate::http::run_http_server(blob_service, auth_service).await + match &config.command { + Some(Command::Cleanup) => blob_service.perform_cleanup().await?, + None | Some(Command::Server) => { + crate::http::run_http_server(blob_service, auth_service).await? + } + }; + + Ok(()) }