-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy paths3.rs
More file actions
142 lines (130 loc) · 3.95 KB
/
s3.rs
File metadata and controls
142 lines (130 loc) · 3.95 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//! Example s3 client running on `wstd` via `wstd_aws`
//!
//! This example is a wasi cli command. It accepts command line arguments
//! with the subcommand `list` to list a bucket's contents, and `get <key>`
//! to get an object from a bucket and write it to the filesystem.
//!
//! This example *must be compiled in release mode* - in debug mode, the aws
//! sdk's generated code will overflow the maximum permitted wasm locals in
//! a single function.
//!
//! Compile it with:
//!
//! ```sh
//! cargo build -p wstd-aws --target wasm32-wasip2 --release --examples
//! ```
//!
//! When running this example, you will need AWS credentials provided in environment
//! variables.
//!
//! Run it with:
//! ```sh
//! wasmtime run -Shttp \
//! --env AWS_ACCESS_KEY_ID \
//! --env AWS_SECRET_ACCESS_KEY \
//! --env AWS_SESSION_TOKEN \
//! --dir .::. \
//! target/wasm22-wasip2/release/examples/s3.wasm
//! ```
//!
//! or alternatively run it with:
//! ```sh
//! cargo run --target wasm32-wasip2 -p wstd-aws --example s3
//! ```
//!
//! which uses the wasmtime cli, as above, via configiration found in this
//! workspace's `.cargo/config`.
//!
//! By default, this script accesses the `wstd-example-bucket` in `us-west-2`.
//! To change the bucket or region, use the `--bucket` and `--region` cli
//! flags before the subcommand.
use anyhow::Result;
use clap::{Parser, Subcommand};
use aws_config::{BehaviorVersion, Region};
use aws_sdk_s3::Client;
#[derive(Debug, Parser)]
#[command(version, about, long_about = None)]
struct Opts {
/// The AWS Region for the s3 bucket.
#[arg(short, long)]
region: String,
/// The name of the s3 bucket.
#[arg(short, long)]
bucket: String,
#[command(subcommand)]
command: Option<Command>,
}
#[derive(Subcommand, Debug)]
enum Command {
List,
Get {
key: String,
#[arg(short, long)]
out: Option<String>,
},
}
#[wstd::main]
async fn main() -> Result<()> {
let opts = Opts::parse();
let region = opts.region;
let bucket = opts.bucket;
let config = aws_config::defaults(BehaviorVersion::latest())
.region(Region::new(region))
.sleep_impl(aws_smithy_wasm::wasi::WasiSleep)
.http_client(aws_smithy_wasm::wasi::WasiHttpClientBuilder::new().build())
.load()
.await;
let client = Client::new(&config);
match opts.command.as_ref().unwrap_or(&Command::List) {
Command::List => {
let output = list(&bucket, &client).await?;
print!("{}", output);
}
Command::Get { key, out } => {
let contents = get(&bucket, &client, key).await?;
let output: &str = if let Some(out) = out {
out.as_str()
} else {
key.as_str()
};
std::fs::write(output, contents)?;
}
}
Ok(())
}
async fn list(bucket: &str, client: &Client) -> Result<String> {
let mut listing = client
.list_objects_v2()
.bucket(bucket.to_owned())
.into_paginator()
.send();
let mut output = String::new();
output += "key\tetag\tlast_modified\tstorage_class\n";
while let Some(res) = listing.next().await {
let object = res?;
for item in object.contents() {
output += &format!(
"{}\t{}\t{}\t{}\n",
item.key().unwrap_or_default(),
item.e_tag().unwrap_or_default(),
item.last_modified()
.map(|lm| format!("{lm}"))
.unwrap_or_default(),
item.storage_class()
.map(|sc| format!("{sc}"))
.unwrap_or_default(),
);
}
}
Ok(output)
}
async fn get(bucket: &str, client: &Client, key: &str) -> Result<Vec<u8>> {
let object = client
.get_object()
.bucket(bucket.to_owned())
.key(key)
.send()
.await?;
let data = object.body.collect().await?;
Ok(data.to_vec())
}