Hello everyone.
We at Qovery are using rust for some parts of our solution, and I'm having an issue with working code using rusoto_s3.
Issue presentation
This is a minimal reproducible example, working for my colleagues, with the same credentials:
use std::error::Error;
use std::future::Future;
use std::io::Read;
use rusoto_core::{Client, HttpClient, Region}; // v0.44.0
use rusoto_credential::StaticProvider; // v0.44.0
use rusoto_s3::{GetObjectRequest, S3Client, S3}; // v0.44.0
use std::env::var;
use tokio::runtime::Runtime;
fn async_run<F: Future>(future: F) -> F::Output {
let mut runtime = Runtime::new().expect("unable to create a tokio runtime");
runtime.block_on(future)
}
fn get_object(
access_key_id: &str,
secret_access_key: &str,
region: Region,
bucket_name: &str,
object_key: &str,
) -> Result<String, Box<dyn Error>> {
let mut s = String::new(); // return value
let s3_client = S3Client::new_with_client(
Client::new_with(
StaticProvider::new(
access_key_id.to_string(),
secret_access_key.to_string(),
None,
None,
),
HttpClient::new().expect("Could not instantiate a new http client??"),
),
region.clone(),
);
let mut or = GetObjectRequest::default();
or.bucket.push_str(bucket_name);
or.key.push_str(object_key);
let oo = s3_client.get_object(or);
let soo = async_run(oo)?;
if let Some(body) // once told me i ain't the sharpest tool in the shed…
= soo.body {
body.into_blocking_read().read_to_string(&mut s)?;
}
else {
panic!("We don't have a body! How are we to experience the world around us?!");
}
Ok(s)
}
fn main() -> Result<(), Box<dyn Error>> {
let access_key_id =
var("AWS_ACCESS_KEY_ID").expect("Please specify AWS_ACCESS_KEY_ID in the env");
let secret_access_key =
var("AWS_SECRET_ACCESS_KEY").expect("Please specify AWS_SECRET_ACCESS_KEY in the env");
let data = get_object(
&access_key_id,
&secret_access_key,
Region::UsEast2,
"kubeconfigs-adwopakdpo221",
"my-eks-on-us-east-2.yaml",
);
match data {
Ok(s) => {
assert_eq!(s.is_empty(), false); // panic!
println!("got data: {}", s);
Ok(())
}
Err(e) => {
println!("Got an error: {}", e);
Err(e)
}
}
}
Each time, i'm having a panic on assert_eq!(s.is_empty(), false);
, meaning we are getting an empty body on our rusoto_s3::GetObjectOutput
.
This very same code works with two of my colleagues, with whom i share the credentials (AWS_*), as they get the file content as stdout. We can all request the file via the aws s3
CLI, but for some reason, I alone can't run the code presented. I've checked & triple checked the credentials, they are not the issue.
Running this code with cargo run
produces the panic on assert_eq
, as well as running it in CLion (still with correct credentials).
HOWEVER: running in debug mode in CLion (with the same run configuration) produces a different behaviour: I'm getting an error (handled in the match data
block), which produces the following output:
Got an error: Request ID: None Body: <?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message><RequestId>
Questions
- Why do i have an empty body and no errors?
- Could you please advise on what could i be doing wrong regarding async -> sync?
Closing words
I realize it is more a library usage question rather than a generic rust question, which is why i've created an issue on their github.
If you read this far, i thank you. Please forgive the possible english errors.