Skip to main content

stack_deploy/
stack.rs

1use crate::types::{OutputKey, StackId, StackIdentifier, StackName};
2
3pub(crate) async fn try_load_stack<T: StackIdentifier>(
4    cloudformation: &aws_sdk_cloudformation::client::Client,
5    stack_identifier: &T,
6) -> Option<aws_sdk_cloudformation::types::Stack> {
7    let response = cloudformation
8        .describe_stacks()
9        .stack_name(stack_identifier.as_str())
10        .send()
11        .await;
12
13    match response {
14        Ok(output) => output.stacks.unwrap().first().cloned(),
15        Err(error) => {
16            let service_error = error.into_service_error();
17            let meta = service_error.meta();
18            let expected_message =
19                format!("Stack with id {} does not exist", stack_identifier.as_str());
20
21            match meta.code() {
22                // There is no nicer way I know to check if a stack exist.
23                Some("ValidationError") if meta.message() == Some(&expected_message) => None,
24                _ => panic!("unexpected service error: {service_error:#?}"),
25            }
26        }
27    }
28}
29
30pub async fn load_stack<T: StackIdentifier>(
31    cloudformation: &aws_sdk_cloudformation::client::Client,
32    stack_identifier: &T,
33) -> aws_sdk_cloudformation::types::Stack {
34    try_load_stack(cloudformation, stack_identifier)
35        .await
36        .unwrap_or_else(|| panic!("stack: {stack_identifier:#?} does not exist!"))
37}
38
39pub(crate) async fn load_stack_id(
40    cloudformation: &aws_sdk_cloudformation::client::Client,
41    stack_name: &StackName,
42) -> StackId {
43    StackId(
44        load_stack(cloudformation, &stack_name)
45            .await
46            .stack_id
47            .unwrap(),
48    )
49}
50
51pub async fn read_stack_output<T: StackIdentifier>(
52    cloudformation: &aws_sdk_cloudformation::client::Client,
53    stack_identifier: &T,
54    output_key: &OutputKey,
55) -> String {
56    log::info!("Reading stack output, stack: {stack_identifier} output: {output_key}");
57
58    load_stack(cloudformation, stack_identifier)
59        .await
60        .outputs()
61        .iter()
62        .find(|output| output.output_key().unwrap() == output_key.0)
63        .unwrap_or_else(|| {
64            panic!(
65                "stack: {:#?} missing output: {}",
66                stack_identifier, output_key.0
67            )
68        })
69        .output_value()
70        .unwrap()
71        .to_string()
72}
73
74#[must_use]
75pub fn fetch_stack_output(
76    stack: &aws_sdk_cloudformation::types::Stack,
77    output_key: &OutputKey,
78) -> String {
79    stack
80        .outputs()
81        .iter()
82        .find(|output| output.output_key().unwrap() == output_key.0)
83        .unwrap_or_else(|| {
84            panic!(
85                "stack: {} missing output: {}",
86                stack.stack_name.as_ref().unwrap(),
87                output_key.0
88            )
89        })
90        .output_value()
91        .unwrap()
92        .to_string()
93}