stack_deploy/lambda/
raw.rs1#[derive(Clone, Debug, clap::Parser)]
2pub struct App {
3 #[clap(subcommand)]
4 command: Command,
5}
6
7#[derive(Clone, Debug, PartialEq)]
8pub struct FunctionName(String);
9
10impl std::str::FromStr for FunctionName {
11 type Err = &'static str;
12
13 fn from_str(input: &str) -> Result<FunctionName, Self::Err> {
14 Ok(Self(String::from(input)))
15 }
16}
17
18impl From<&FunctionName> for String {
19 fn from(value: &FunctionName) -> Self {
20 value.0.clone()
21 }
22}
23
24impl App {
25 pub async fn run(&self, lambda: &aws_sdk_lambda::client::Client) {
26 self.command.run(lambda).await
27 }
28}
29
30#[derive(Clone, Debug, clap::ValueEnum)]
31pub enum OutputFormat {
32 JSON,
33 RAW,
34}
35
36impl OutputFormat {
37 fn print(&self, body: aws_sdk_lambda::primitives::Blob) {
38 match self {
39 Self::JSON => Self::print_json(body),
40 Self::RAW => Self::print_raw(body),
41 }
42 }
43
44 fn print_raw(body: aws_sdk_lambda::primitives::Blob) {
45 println!("{body:#?}")
46 }
47
48 fn print_json(body: aws_sdk_lambda::primitives::Blob) {
49 println!(
50 "{}",
51 serde_json::from_slice::<serde_json::Value>(body.into_inner().as_ref()).unwrap()
52 )
53 }
54}
55
56#[derive(Clone, Debug, clap::Parser)]
57pub enum Command {
58 Invoke {
60 #[arg(long = "function-name")]
62 function_name: FunctionName,
63 #[arg(long = "output-format")]
65 output_format: OutputFormat,
66 },
67}
68
69impl Command {
70 pub async fn run(&self, lambda: &aws_sdk_lambda::client::Client) {
71 match self {
72 Self::Invoke {
73 function_name,
74 output_format,
75 } => invoke(lambda, function_name, output_format).await,
76 }
77 }
78}
79
80#[must_use]
81pub fn decode_log(log_result: Option<String>) -> String {
82 log_result.map_or_else(
83 || String::from("Log field empty!"),
84 |result| {
85 base64::Engine::decode(&base64::engine::general_purpose::STANDARD, result).map_or_else(
86 |error| format!("Log base64 decode failed!: {error:#?}"),
87 |bytes| {
88 String::from_utf8(bytes)
89 .unwrap_or_else(|error| format!("Log utf8 decode failed!: {error:#?}"))
90 },
91 )
92 },
93 )
94}
95
96async fn invoke(
97 lambda: &aws_sdk_lambda::client::Client,
98 function_name: &FunctionName,
99 output_format: &OutputFormat,
100) {
101 let response = lambda
102 .invoke()
103 .function_name(function_name)
104 .log_type(aws_sdk_lambda::types::LogType::Tail)
105 .send()
106 .await;
107
108 match response {
109 Err(error) => panic!(
110 "Lambda function failed to invoke: {:#?}",
111 error.into_service_error()
112 ),
113 Ok(output) => {
114 if let Some(error) = output.function_error {
115 panic!(
116 "Lambda invoked but errored: Function Error: {:#?}, log: {}",
117 error,
118 decode_log(output.log_result)
119 )
120 } else {
121 output_format.print(output.payload.unwrap())
122 }
123 }
124 }
125}