four_lambda 0.0.6

framework for creating AWS CloudFormation template
Documentation
use four::{
    arn::Arn,
    convert::{WillBe, WillMappable},
    function::{
        getatt::{Attribute, HaveAtt},
        reference::{RefInner, Referenced},
    },
    logical_id::LogicalId,
    service::Lambda,
    ManagedResource,
};
use four_iam::resource::role::RoleArn;
use serde::Serialize;

use crate::property::{
    architecture::{Architecture, Architectures},
    code::Code,
    handler::Handler,
    memory_size::{MemorySize, MemorySizeError},
    runtime::Runtime,
};

#[derive(ManagedResource, Clone)]
#[resource_type = "AWS::Lambda::Function"]
pub struct Function {
    logical_id: LogicalId,
    architectures: Architectures,
    code: Code,
    description: Option<String>,
    function_name: Option<WillBe<FunctionName>>,
    handler: Option<Handler>,
    memory_size: Option<MemorySize>,
    role: WillBe<RoleArn>,
    runtime: Option<Runtime>,
    timeout: Option<Timeout>,
}

impl Function {
    pub fn new(logical_id: LogicalId, code: Code, role: WillBe<RoleArn>) -> Function {
        Function {
            logical_id,
            architectures: Architectures::x86_64(),
            code,
            description: None,
            function_name: None,
            handler: None,
            memory_size: None,
            role,
            runtime: None,
            timeout: None,
        }
    }

    pub fn zip(
        logical_id: LogicalId,
        bucket_name: &str,
        key: &str,
        role: WillBe<RoleArn>,
        handler: Handler,
        runtime: Runtime,
    ) -> Function {
        let code = Code::new(bucket_name, key);

        Function::new(logical_id, code, role)
            .handler(handler)
            .runtime(runtime)
    }

    pub fn architecture(mut self, architecture: Architecture) -> Self {
        self.architectures = Architectures::with(architecture);
        self
    }

    pub fn description(mut self, description: &str) -> Self {
        self.description = Some(description.to_string());
        self
    }

    pub fn handler(mut self, handler: Handler) -> Self {
        self.handler = Some(handler);
        self
    }

    pub fn memory_size(mut self, value: usize) -> Result<Self, MemorySizeError> {
        let value = MemorySize::try_from(value)?;
        self.memory_size = Some(value);
        Ok(self)
    }

    pub fn runtime(mut self, runtime: Runtime) -> Self {
        self.runtime = Some(runtime);
        self
    }

    pub fn timeout(mut self, timeout: usize) -> Result<Self, TimeoutError> {
        let timeout = Timeout::try_from(timeout)?;
        self.timeout = Some(timeout);
        Ok(self)
    }
}

#[derive(Debug, Clone, Serialize)]
pub struct FunctionName(String);

impl TryFrom<&str> for FunctionName {
    type Error = FunctionNameError;

    fn try_from(value: &str) -> Result<Self, Self::Error> {
        if value.len() == 0 {
            Err(FunctionNameError::Invalid(value.to_string()))
        } else {
            Ok(FunctionName(value.to_string()))
        }
    }
}

impl Referenced for Function {
    type To = Arn<Lambda>;

    fn referenced(&self) -> RefInner {
        RefInner::Id(self.logical_id.clone())
    }
}

impl WillMappable<String> for FunctionName {}

#[derive(Debug, thiserror::Error)]
pub enum FunctionNameError {
    #[error("invalid function name: {0}")]
    Invalid(String),
}

#[derive(Debug, Clone, Serialize)]
pub struct Timeout(usize);

impl TryFrom<usize> for Timeout {
    type Error = TimeoutError;

    fn try_from(value: usize) -> Result<Self, Self::Error> {
        if value == 0 || value > 900 {
            Err(TimeoutError::Invalid(value))
        } else {
            Ok(Timeout(value))
        }
    }
}

#[derive(Debug, thiserror::Error)]
pub enum TimeoutError {
    #[error("invalid timeout: {0}")]
    Invalid(usize),
}

#[derive(Debug, Clone, Serialize)]
pub struct FunctionArn(Arn<Lambda>);

impl From<Arn<Lambda>> for FunctionArn {
    fn from(value: Arn<Lambda>) -> Self {
        FunctionArn(value)
    }
}

impl HaveAtt<FunctionArn> for Function {}

impl Attribute for FunctionArn {
    fn name() -> &'static str {
        "Arn"
    }
}

#[cfg(test)]
mod tests {
    use four::account::{Account, AccountDetail};

    use super::*;

    #[test]
    fn test_function1() {
        let id = LogicalId::try_from("function-id").unwrap();
        let code = Code::new("mybucket", "mykey");
        let account = Account::Detail(AccountDetail::try_from("123456789012").unwrap());

        let role = Arn::builder("iam", "abc", account).build();
        let function = Function::new(id, code, role);
    }
}