use std::{
collections::HashMap,
fs::File,
io::{Cursor, Write},
path::PathBuf,
time::Duration,
};
use aws_sdk_iam::primitives::Blob;
use aws_sdk_lambda::types::{Environment, FunctionCode, FunctionUrlAuthType, InvokeMode};
use rand::{distributions::Alphanumeric, Rng};
use zip::{write::SimpleFileOptions, ZipWriter};
use crate::manifest::Entrypoint;
pub async fn deploy(
name: &str,
entrypoint: &Entrypoint,
binary_path: PathBuf,
iam: &aws_sdk_iam::Client,
lambda: &aws_sdk_lambda::Client,
computed_env: HashMap<String, String>,
) -> (String, String) {
let hash: String = rand::thread_rng()
.sample_iter(&Alphanumeric)
.take(7)
.map(char::from)
.collect();
let fn_name = format!("{}-{}", name, hash);
let mut zip_file = Cursor::new(vec![]);
{
let mut zip = ZipWriter::new(&mut zip_file);
zip.start_file("bootstrap", SimpleFileOptions::default())
.unwrap();
let mut binary = File::open(&binary_path).unwrap();
std::io::copy(&mut binary, &mut zip).unwrap();
zip.finish().unwrap();
zip_file.flush().unwrap();
}
let code = FunctionCode::builder()
.zip_file(Blob::new(zip_file.into_inner()))
.build();
let role = iam
.create_role()
.role_name(format!("{fn_name}-role"))
.assume_role_policy_document(ROLE_POLICY_DOCUMENT)
.send()
.await
.unwrap();
println!("Created iam role, waiting 5s for it to become active");
tokio::time::sleep(Duration::from_secs(5)).await;
let role = role.role().unwrap();
let function_resp = lambda
.create_function()
.function_name(&fn_name)
.description("Specta Start demo")
.runtime(aws_sdk_lambda::types::Runtime::Providedal2023)
.code(code)
.role(role.arn())
.handler("bootstrap")
.environment(
Environment::builder()
.set_variables(Some(computed_env))
.build(),
)
.send()
.await
.unwrap();
println!(
"Created function {fn_name} {} in {}",
function_resp.function_arn().unwrap(),
"us-east-1"
);
{
lambda
.add_permission()
.function_name(&fn_name)
.action("lambda:InvokeFunctionUrl")
.function_url_auth_type(FunctionUrlAuthType::None)
.principal("*")
.statement_id("FunctionURLAllowPublicAccess")
.send()
.await
.unwrap();
let resp = lambda
.create_function_url_config()
.function_name(&fn_name)
.auth_type(FunctionUrlAuthType::None)
.invoke_mode(InvokeMode::Buffered)
.send()
.await
.unwrap();
println!("Created function URL for {fn_name}: {}", resp.function_url);
}
(function_resp.function_arn().unwrap().into(), "todo".into())
}
const ROLE_POLICY_DOCUMENT: &str = r#"{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "lambda.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}"#;