#[allow(clippy::too_many_arguments)]
pub mod cli;
pub mod error;
#[cfg(test)]
mod tests;
use aws_sdk_s3::model::{
BucketLocationConstraint, CreateBucketConfiguration, Delete, ObjectIdentifier,
};
use aws_sdk_s3::output::ListObjectsV2Output;
use aws_sdk_s3::types::ByteStream;
use aws_sdk_s3::{Client, Error};
use std::str;
use tracing::{event, Level};
pub async fn delete_bucket(client: &Client, bucket_name: &str) -> Result<(), Error> {
client.delete_bucket().bucket(bucket_name).send().await?;
event!(Level::INFO, "Deleted bucket {}", bucket_name);
Ok(())
}
pub async fn delete_objects(client: &Client, bucket_name: &str) -> Result<(), Error> {
let objects = client.list_objects_v2().bucket(bucket_name).send().await?;
let mut delete_objects: Vec<ObjectIdentifier> = vec![];
for obj in objects.contents().unwrap_or_default() {
let obj_id = ObjectIdentifier::builder()
.set_key(Some(obj.key().unwrap().to_string()))
.build();
delete_objects.push(obj_id);
}
client
.delete_objects()
.bucket(bucket_name)
.delete(Delete::builder().set_objects(Some(delete_objects)).build())
.send()
.await?;
let objects: ListObjectsV2Output = client.list_objects_v2().bucket(bucket_name).send().await?;
match objects.key_count {
0 => Ok(()),
_ => Err(Error::Unhandled(Box::from(
"There were still objects left in the bucket.",
))),
}
}
pub async fn list_objects(client: &Client, bucket_name: &str) -> Result<(), Error> {
let objects = client.list_objects_v2().bucket(bucket_name).send().await?;
println!("Objects in bucket:");
for obj in objects.contents().unwrap_or_default() {
println!("{:?}", obj.key().unwrap());
}
Ok(())
}
pub async fn copy_object(
client: &Client,
bucket_name: &str,
object_key: &str,
target_key: &str,
) -> Result<(), Error> {
let mut source_bucket_and_object: String = "".to_owned();
source_bucket_and_object.push_str(bucket_name);
source_bucket_and_object.push('/');
source_bucket_and_object.push_str(object_key);
client
.copy_object()
.copy_source(source_bucket_and_object)
.bucket(bucket_name)
.key(target_key)
.send()
.await?;
event!(
Level::INFO,
"Copied {}/{} to {}/{}",
bucket_name,
object_key,
bucket_name,
target_key
);
Ok(())
}
pub async fn download_object(client: &Client, bucket: &str, key: &str) -> Result<(), Error> {
client.get_object().bucket(bucket).key(key).send().await?;
Ok(())
}
pub async fn upload_object_zstd(
data_uncompressed: &[u8],
client: &Client,
bucket_name: &str,
key: &str,
) -> Result<(), Error> {
let body_compressed = ByteStream::from(zstd::bulk::compress(data_uncompressed, 0).unwrap());
client
.put_object()
.bucket(bucket_name)
.key(key)
.body(body_compressed)
.content_type("application/octet-stream")
.content_encoding("zstd")
.send()
.await?;
event!(
Level::INFO,
"Uploaded zstd compressed object at key {} to bucket {}",
key,
bucket_name,
);
Ok(())
}
pub async fn create_bucket(client: &Client, bucket_name: &str, region: &str) -> Result<(), Error> {
let constraint = BucketLocationConstraint::from(region);
let cfg = CreateBucketConfiguration::builder()
.location_constraint(constraint)
.build();
client
.create_bucket()
.create_bucket_configuration(cfg)
.bucket(bucket_name)
.send()
.await?;
event!(
Level::INFO,
"Created bucket {} in region {}",
bucket_name,
region,
);
Ok(())
}