From 4526fb9cbca8fa410a6a9ba25eba4064d3b4c03e Mon Sep 17 00:00:00 2001 From: Vignesh Rao Date: Mon, 29 Jul 2024 15:58:43 -0500 Subject: [PATCH] Release `v0.0.2` Update all docstrings Bump all dependency versions Add doc specs and make crate a lib --- .github/workflows/rust.yaml | 4 +- Cargo.toml | 27 +++++++++---- README.md | 10 +++-- src/aws.rs | 35 +++++++++++++++++ src/lib.rs | 69 +++++++++++++++++++++++++++++++++ src/main.rs | 53 +------------------------ src/squire/settings.rs | 31 ++++++++++++++- src/templates/list_bootstrap.rs | 5 +++ src/templates/list_vanilla.rs | 5 +++ 9 files changed, 172 insertions(+), 67 deletions(-) create mode 100644 src/lib.rs diff --git a/.github/workflows/rust.yaml b/.github/workflows/rust.yaml index 8e7123d..73d15e3 100644 --- a/.github/workflows/rust.yaml +++ b/.github/workflows/rust.yaml @@ -46,7 +46,7 @@ jobs: id: set-release-flag run: | git pull - if git tag --list | grep "${{ env.pkg_version }}"; then + if git tag --list | grep "^${{ env.pkg_version }}$"; then echo "Version ${{ env.pkg_version }} exists in tags, setting release flag to 'false'" echo "release=false" >> $GITHUB_ENV echo "release=false" >> "$GITHUB_OUTPUT" @@ -191,7 +191,7 @@ jobs: - release - upload_assets if: needs.release.outputs.release-flag == 'true' - runs-on: thevickypedia-lite + runs-on: thevickypedia-default steps: - uses: actions/checkout@v4 - name: Update Rust diff --git a/Cargo.toml b/Cargo.toml index 3d2e93d..784116f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "lists3" -version = "0.0.1" +version = "0.0.2" description = "Service that creates object listing functionality for S3 buckets" edition = "2021" authors = ["Vignesh Rao"] @@ -14,15 +14,26 @@ categories = ["filesystem", "embedded", "development-tools", "visualization"] include = ["/src", "LICENSE"] exclude = [".github", ".gitignore", "README.md"] +[lib] +name = "lists3" +path = "src/lib.rs" + [[bin]] name = "lists3" path = "src/main.rs" +# Docs release queue +# https://docs.rs/releases/queue +# Verify docs locally +# cargo doc --no-deps --document-private-items --open +[package.metadata.docs.rs] +rustdoc-args = ["--document-private-items"] + [dependencies] -minijinja = { version = "2.0.1", features = ["loader"] } -url = "2.5.0" -serde = { version = "1.0.196", features = ["derive"] } -serde_json = "1.0.113" -aws-sdk-s3 = { version = "1", features = ["behavior-version-latest"] } -aws-config = { version = "1", features = ["behavior-version-latest"] } -tokio = { version = "1.37.0", features = ["full"] } +minijinja = { version = "2.1.0", features = ["loader"] } +url = "2.5.2" +serde = { version = "1.0.202", features = ["derive"] } +serde_json = "1.0.121" +aws-sdk-s3 = { version = "1.42.0", features = ["behavior-version-latest"] } +aws-config = { version = "1.5.4", features = ["behavior-version-latest"] } +tokio = { version = "1.39.2", features = ["full"] } diff --git a/README.md b/README.md index 7c55692..db8602c 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ +# ListS3 + +[![made-with-rust][rust-logo]][rust-src-page] + [![crates.io][crates-logo]][crate] [![build][gh-logo]][build] #### Summary -[`lists3`][repo] is a self-hosted streaming engine, that can render media files via authenticated sessions. - -# ListS3 -File Browser for S3 buckets +[`lists3`][repo] is a light-weight CLI tool to create a file browser for S3 buckets provisioning bucket listing.
Download pre-compiled OS specific executable @@ -79,6 +80,7 @@ cargo clippy --no-deps --fix Licensed under the [MIT License][license] +[rust-src-page]: https://www.rust-lang.org/ [repo]: https://github.com/thevickypedia/lists3 [license]: https://github.com/thevickypedia/lists3/blob/main/LICENSE [build]: https://github.com/thevickypedia/lists3/actions/workflows/rust.yaml diff --git a/src/aws.rs b/src/aws.rs index feb1e48..260219c 100644 --- a/src/aws.rs +++ b/src/aws.rs @@ -9,6 +9,15 @@ use aws_sdk_s3::types::Bucket; use crate::squire; +/// Creates an AWS S3 client using the specified region. +/// +/// # Arguments +/// +/// * `region` - A reference to the AWS region to be used for the client. +/// +/// # Returns +/// +/// Returns an instance of `Client` configured for the specified region. pub async fn get_client( region: &Region ) -> Client { @@ -18,6 +27,15 @@ pub async fn get_client( Client::new(&config) } +/// Determines the AWS region to be used based on the provided configuration. +/// +/// # Arguments +/// +/// * `config` - Configuration settings passed as flags or env vars. +/// +/// # Returns +/// +/// Returns an instance of `Region` based on the configuration or the default provider. pub async fn get_region( config: &squire::settings::Config ) -> Region { @@ -31,6 +49,15 @@ pub async fn get_region( } } +/// Retrieves a list of all S3 buckets in the configured region. +/// +/// # Arguments +/// +/// * `client` - A reference to the AWS S3 client. +/// +/// # Returns +/// +/// Returns an `Option>` containing the list of buckets if successful. pub async fn get_buckets( client: &Client ) -> Option> { @@ -43,6 +70,14 @@ pub async fn get_buckets( } } +/// Uploads an object to the specified S3 bucket. +/// +/// # Arguments +/// +/// * `client` - A reference to the AWS S3 client. +/// * `bucket_name` - The name of the bucket to upload the object to. +/// * `data` - The content of the object to be uploaded. +/// * `file_name` - The name of the object to be uploaded. pub async fn upload_object( client: &Client, bucket_name: &String, diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..1563ff0 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,69 @@ +#![allow(rustdoc::bare_urls)] +#![doc = include_str!("../README.md")] + +use std; + +use aws_config::Region; + +mod templates; +mod squire; +mod aws; + +/// Generates the HTML file required with template. +/// +/// # Arguments +/// +/// * `config` - Configuration settings passed as flags or env vars. +/// * `region` - Reference to the AWS region object. +/// * `metadata` - Project's metadata information stored as a struct. +/// +/// # Returns +/// +/// Returns a `String` response of the HTML page. +async fn generate_html( + config: &squire::settings::Config, + region: &Region, + metadata: &squire::constant::MetaData +) -> String { + let jinja = templates::environment(); + let template_string = format!("list-s3-{}", config.style); + let list_object = jinja.get_template(template_string.as_str()).unwrap(); + let html_data = list_object.render(minijinja::context!( + bucket_name => config.bucket, + region_name => region.to_string(), + folder_names => config.filter, + ignore_objects => config.ignore, + proxy_server => config.proxy.to_string(), + cargo_version => metadata.pkg_version + )); + html_data.unwrap() +} + +/// Initializes the application and uploads the generated HTML to S3. +pub async fn initiate() { + let metadata = squire::constant::build_info(); + let config = squire::parser::arguments(&metadata); + + let region = aws::get_region(&config).await; + let aws_client = aws::get_client(®ion).await; + + let mut bucket_names = Vec::new(); + match aws::get_buckets(&aws_client).await { + Some(buckets) => { + for bucket in buckets { + bucket_names.push(bucket.name.unwrap()); + } + } + None => { + eprintln!("Failed to fetch S3 buckets."); + std::process::exit(1) + } + } + if !bucket_names.contains(&config.bucket) { + eprintln!("\n{:?}\n\tBucket name is invalid.\n\tExpected one of {:?}\n", + &config.bucket, bucket_names); + std::process::exit(1) + } + let data = generate_html(&config, ®ion, &metadata).await; + aws::upload_object(&aws_client, &config.bucket, &data, &config.object).await; +} diff --git a/src/main.rs b/src/main.rs index 3dfbf72..3aac5ab 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,55 +1,4 @@ -use std::process::exit; - -use aws_config::Region; - -mod templates; -mod squire; -mod aws; - -async fn generate_html( - config: &squire::settings::Config, - region: &Region, - metadata: &squire::constant::MetaData -) -> String { - let jinja = templates::environment(); - let template_string = format!("list-s3-{}", config.style); - let list_object = jinja.get_template(template_string.as_str()).unwrap(); - let html_data = list_object.render(minijinja::context!( - bucket_name => config.bucket, - region_name => region.to_string(), - folder_names => config.filter, - ignore_objects => config.ignore, - proxy_server => config.proxy.to_string(), - cargo_version => metadata.pkg_version - )); - html_data.unwrap() -} - #[tokio::main] async fn main() { - let metadata = squire::constant::build_info(); - let config = squire::parser::arguments(&metadata); - - let region = aws::get_region(&config).await; - let aws_client = aws::get_client(®ion).await; - - let mut bucket_names = Vec::new(); - match aws::get_buckets(&aws_client).await { - Some(buckets) => { - for bucket in buckets { - bucket_names.push(bucket.name.unwrap()); - } - } - None => { - eprintln!("Failed to fetch S3 buckets."); - exit(1) - } - } - if !bucket_names.contains(&config.bucket) { - eprintln!("\n{:?}\n\tBucket name is invalid.\n\tExpected one of {:?}\n", - &config.bucket, bucket_names); - exit(1) - } - let data = generate_html(&config, ®ion, &metadata).await; - aws::upload_object(&aws_client, &config.bucket, &data, &config.object).await; + lists3::initiate().await } diff --git a/src/squire/settings.rs b/src/squire/settings.rs index cf18c61..6cb5679 100644 --- a/src/squire/settings.rs +++ b/src/squire/settings.rs @@ -21,7 +21,7 @@ pub struct Config { /// /// # Panics /// -/// If the value is present, but it is an invalid data-type. +/// This function will print an error message and terminate the program if the value is present, but it is an invalid data-type. fn parse_vec(value: &str) -> Option> { if value.is_empty() { return None; @@ -42,6 +42,15 @@ fn parse_vec(value: &str) -> Option> { } } +/// Extracts the argument and parses it as a `Url` +/// +/// # Returns +/// +/// Returns a `Url` if the value is available. +/// +/// # Panics +/// +/// This function will print an error message and terminate the program if the value is not a valid URL. fn parse_url(string: &str) -> Url { if string.is_empty() { return Url::parse("https://jarvis.vigneshrao.com/proxy").unwrap() @@ -52,6 +61,26 @@ fn parse_url(string: &str) -> Url { }) } +/// Parses the configuration for the application and returns a `Config` struct. +/// +/// # Arguments +/// +/// * `bucket` - The name of the S3 bucket. This is a mandatory field. +/// * `region` - The AWS region where the bucket is located. +/// * `filter` - A string representing filters to be applied, which will be parsed into a vector. +/// * `ignore` - A string representing patterns to be ignored, which will be parsed into a vector. +/// * `object` - The name of the object to be operated on. +/// * `proxy` - The proxy URL to be used, which will be parsed. +/// * `style` - The style option for the output. Expected values are "bootstrap" or "vanilla". +/// +/// # Returns +/// +/// Returns a `Config` struct populated with the parsed values. +/// +/// # Panics +/// +/// This function will print an error message and terminate the program if the `bucket` field is empty or if the `style` +/// option is invalid. pub fn parse_config( bucket: String, region: String, diff --git a/src/templates/list_bootstrap.rs b/src/templates/list_bootstrap.rs index 9571734..099b41a 100644 --- a/src/templates/list_bootstrap.rs +++ b/src/templates/list_bootstrap.rs @@ -1,3 +1,8 @@ +/// Loads the HTML content for listing S3 contents with bootstrap template. +/// +/// # Returns +/// +/// Returns the HTML content as a `String` pub fn get_content() -> String { r###" diff --git a/src/templates/list_vanilla.rs b/src/templates/list_vanilla.rs index 5c8d135..f2ab0d4 100644 --- a/src/templates/list_vanilla.rs +++ b/src/templates/list_vanilla.rs @@ -1,3 +1,8 @@ +/// Loads the HTML content for listing S3 contents with vanilla JS template. +/// +/// # Returns +/// +/// Returns the HTML content as a `String` pub fn get_content() -> String { r###"