cfn/
lib.rs

1#![deny(missing_docs)]
2#![deny(warnings)]
3#![deny(missing_debug_implementations)]
4
5//! This crate provides type-safe representations for AWS CloudFormation templates,
6//! resources and properties.
7
8extern crate indexmap;
9extern crate serde;
10#[macro_use] extern crate serde_derive;
11extern crate serde_json;
12
13mod error;
14#[macro_use] mod codec;
15mod types;
16mod parts;
17pub mod aws;
18
19pub use error::{Error, ErrorKind};
20pub use types::*;
21pub use parts::*;
22
23pub mod json {
24    //! Types for raw JSON values.
25    pub use serde_json::{Value, Number};
26}
27
28/// Represents an AWS CloudFormation template.
29#[derive(Debug, Default, Serialize, Deserialize)]
30pub struct Template {
31    #[serde(rename = "Description", default, skip_serializing_if = "Option::is_none")]
32    description: Option<String>,
33    #[serde(rename = "Resources", default)]
34    resources: Resources,
35    #[serde(rename = "Outputs", default)]
36    outputs: Outputs
37}
38
39impl Template {
40    /// Get the template description as a reference.
41    pub fn description(&self) -> &Option<String> {
42        &self.description
43    }
44
45    /// Get the template description as a mutable reference.
46    pub fn description_mut(&mut self) -> &mut Option<String> {
47        &mut self.description
48    }
49
50    /// Get a reference to the resources defined in the template.
51    pub fn resources(&self) -> &Resources {
52        &self.resources
53    }
54
55    /// Get a mutable reference to the resources defined in the template.
56    pub fn resources_mut(&mut self) -> &mut Resources {
57        &mut self.resources
58    }
59
60    /// Get a reference to the outputs defined in the template.
61    pub fn outputs(&self) -> &Outputs {
62        &self.outputs
63    }
64
65    /// Get a mutable reference to the outputs defined in the template.
66    pub fn outputs_mut(&mut self) -> &mut Outputs {
67        &mut self.outputs
68    }
69}
70
71impl Template {
72    /// Deserialize a AWS CloudFormation template in JSON format.
73    pub fn from_json<T: AsRef<str>>(input: T) -> Result<Template, ::Error> {
74        serde_json::from_str(input.as_ref())
75            .map_err(|err| ::Error::new(::ErrorKind::Serialization, err))
76    }
77
78    /// Serialize the template into an AWS CloudFormation template in JSON format.
79    pub fn to_json(&self) -> Result<String, ::Error> {
80        serde_json::to_string(self)
81            .map_err(|err| ::Error::new(::ErrorKind::Serialization, err))
82    }
83}
84
85/// Trait for stack resources, such as an Amazon Elastic Compute Cloud instance or an Amazon Simple Storage Service bucket.
86pub trait Resource: Sized + private::Sealed {
87    /// Uniquely identifies the resource type. 
88    const TYPE: &'static str;
89    /// Type that represents the set of properties the resource can be configured with.
90    type Properties: private::Properties<Self>;
91
92    /// Get a reference to the properties on the resource.
93    fn properties(&self) -> &Self::Properties;
94    /// Get a mutable reference to the properties on the resource.
95    fn properties_mut(&mut self) -> &mut Self::Properties;
96}
97
98mod private {
99    pub trait Sealed {}
100
101    pub trait Properties<R>: Into<R> + ::serde::Serialize + ::serde::de::DeserializeOwned {}
102    impl<P, R> Properties<R> for P where P: Into<R> + ::serde::Serialize + ::serde::de::DeserializeOwned {}
103}
104
105#[cfg(test)]
106mod tests {
107    use serde_json::to_value;
108    use super::Template;
109
110    #[test]
111    fn deserialize_empty_template() {
112        let tpl = Template::from_json("{}").unwrap();
113        assert!(tpl.description().is_none())
114    }
115
116    #[test]
117    fn serialize_empty_template() {
118        let tpl = Template::default();
119        let val = to_value(&tpl).unwrap();
120        let obj = val.as_object().unwrap();
121        assert_eq!(2, obj.len());
122        assert_eq!(false, obj.contains_key("Description"));
123        assert_eq!(true, obj.contains_key("Resources"));
124        assert_eq!(true, obj.contains_key("Outputs"));
125    }
126}