Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions lambda-events/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ default = [
"autoscaling",
"chime_bot",
"clientvpn",
"cloudformation",
"cloudwatch_events",
"cloudwatch_logs",
"code_commit",
Expand Down Expand Up @@ -81,6 +82,7 @@ appsync = []
autoscaling = ["chrono"]
chime_bot = ["chrono"]
clientvpn = []
cloudformation = []
cloudwatch_events = ["chrono"]
cloudwatch_logs = ["flate2"]
code_commit = ["chrono"]
Expand Down
134 changes: 134 additions & 0 deletions lambda-events/src/event/cloudformation/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
use serde::{de::DeserializeOwned, Deserialize, Serialize};
use serde_json::Value;

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(tag = "RequestType")]
pub enum CloudFormationCustomResourceRequest<P1 = Value, P2 = Value>
where
P1: DeserializeOwned + Serialize,
P2: DeserializeOwned + Serialize,
{
#[serde(bound = "")]
Create(CreateRequest<P2>),
#[serde(bound = "")]
Update(UpdateRequest<P1, P2>),
#[serde(bound = "")]
Delete(DeleteRequest<P2>),
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "PascalCase")]
#[serde(deny_unknown_fields)]
pub struct CreateRequest<P2 = Value>
where
P2: DeserializeOwned + Serialize,
{
#[serde(default)]
pub service_token: Option<String>,
pub request_id: String,
#[serde(rename = "ResponseURL")]
pub response_url: String,
pub stack_id: String,
pub resource_type: String,
pub logical_resource_id: String,
#[serde(bound = "")]
pub resource_properties: P2,
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "PascalCase")]
#[serde(deny_unknown_fields)]
pub struct UpdateRequest<P1 = Value, P2 = Value>
where
P1: DeserializeOwned + Serialize,
P2: DeserializeOwned + Serialize,
{
#[serde(default)]
pub service_token: Option<String>,
pub request_id: String,
#[serde(rename = "ResponseURL")]
pub response_url: String,
pub stack_id: String,
pub resource_type: String,
pub logical_resource_id: String,
pub physical_resource_id: String,
#[serde(bound = "")]
pub resource_properties: P2,
#[serde(bound = "")]
pub old_resource_properties: P1,
}

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "PascalCase")]
#[serde(deny_unknown_fields)]
pub struct DeleteRequest<P2 = Value>
where
P2: DeserializeOwned + Serialize,
{
#[serde(default)]
pub service_token: Option<String>,
pub request_id: String,
#[serde(rename = "ResponseURL")]
pub response_url: String,
pub stack_id: String,
pub resource_type: String,
pub logical_resource_id: String,
pub physical_resource_id: String,
#[serde(bound = "")]
pub resource_properties: P2,
}

#[cfg(test)]
mod test {
use std::collections::HashMap;

use super::CloudFormationCustomResourceRequest::*;
use super::*;

#[derive(Clone, Debug, Deserialize, PartialEq, Serialize)]
#[serde(rename_all = "PascalCase")]
#[serde(deny_unknown_fields)]
struct TestProperties {
key_1: String,
key_2: Vec<String>,
key_3: HashMap<String, String>,
}

type TestRequest = CloudFormationCustomResourceRequest<TestProperties, TestProperties>;

#[test]
fn example_cloudformation_custom_resource_create_request() {
let data = include_bytes!("../../fixtures/example-cloudformation-custom-resource-create-request.json");
let parsed: TestRequest = serde_json::from_slice(data).unwrap();

let Create(_) = parsed else { panic!("expected Create request") };

let output: String = serde_json::to_string(&parsed).unwrap();
let reparsed: TestRequest = serde_json::from_slice(output.as_bytes()).unwrap();
assert_eq!(parsed, reparsed);
}

#[test]
fn example_cloudformation_custom_resource_update_request() {
let data = include_bytes!("../../fixtures/example-cloudformation-custom-resource-update-request.json");
let parsed: TestRequest = serde_json::from_slice(data).unwrap();

let Update(_) = parsed else { panic!("expected Update request") };

let output: String = serde_json::to_string(&parsed).unwrap();
let reparsed: TestRequest = serde_json::from_slice(output.as_bytes()).unwrap();
assert_eq!(parsed, reparsed);
}

#[test]
fn example_cloudformation_custom_resource_delete_request() {
let data = include_bytes!("../../fixtures/example-cloudformation-custom-resource-delete-request.json");
let parsed: TestRequest = serde_json::from_slice(data).unwrap();

let Delete(_) = parsed else { panic!("expected Delete request") };

let output: String = serde_json::to_string(&parsed).unwrap();
let reparsed: TestRequest = serde_json::from_slice(output.as_bytes()).unwrap();
assert_eq!(parsed, reparsed);
}
}
4 changes: 4 additions & 0 deletions lambda-events/src/event/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ pub mod chime_bot;
#[cfg(feature = "clientvpn")]
pub mod clientvpn;

/// AWS Lambda event definitions for cloudformation.
#[cfg(feature = "cloudformation")]
pub mod cloudformation;

/// CloudWatch Events payload
#[cfg(feature = "cloudwatch_events")]
pub mod cloudwatch_events;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"ServiceToken": "arn:aws:lambda:eu-west-2:123456789012:function:custom-resource-handler",
"RequestType" : "Create",
"RequestId" : "82304eb2-bdda-469f-a33b-a3f1406d0a52",
"ResponseURL": "https://cr-response-bucket.s3.us-east-1.amazonaws.com/cr-response-key?sig-params=sig-values",
"StackId" : "arn:aws:cloudformation:us-east-1:123456789012:stack/stack-name/16580499-7622-4a9c-b32f-4eba35da93da",
"ResourceType" : "Custom::MyCustomResourceType",
"LogicalResourceId" : "CustomResource",
"ResourceProperties" : {
"Key1" : "string",
"Key2" : [ "list" ],
"Key3" : { "Key4" : "map" }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"ServiceToken": "arn:aws:lambda:eu-west-2:123456789012:function:custom-resource-handler",
"RequestType" : "Delete",
"RequestId" : "ef70561d-d4ba-42a4-801b-33ad88dafc37",
"ResponseURL": "https://cr-response-bucket.s3.us-east-1.amazonaws.com/cr-response-key?sig-params=sig-values",
"StackId" : "arn:aws:cloudformation:us-east-1:123456789012:stack/stack-name/16580499-7622-4a9c-b32f-4eba35da93da",
"ResourceType" : "Custom::MyCustomResourceType",
"LogicalResourceId" : "CustomResource",
"PhysicalResourceId" : "custom-resource-f4bd5382-3de3-4caf-b7ad-1be06b899647",
"ResourceProperties" : {
"Key1" : "string",
"Key2" : [ "list" ],
"Key3" : { "Key4" : "map" }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"ServiceToken": "arn:aws:lambda:eu-west-2:123456789012:function:custom-resource-handler",
"RequestType" : "Update",
"RequestId" : "49347ca5-c603-44e5-a34b-10cf1854a887",
"ResponseURL": "https://cr-response-bucket.s3.us-east-1.amazonaws.com/cr-response-key?sig-params=sig-values",
"StackId" : "arn:aws:cloudformation:us-east-1:123456789012:stack/stack-name/16580499-7622-4a9c-b32f-4eba35da93da",
"ResourceType" : "Custom::MyCustomResourceType",
"LogicalResourceId" : "CustomResource",
"PhysicalResourceId" : "custom-resource-f4bd5382-3de3-4caf-b7ad-1be06b899647",
"ResourceProperties" : {
"Key1" : "new-string",
"Key2" : [ "new-list" ],
"Key3" : { "Key4" : "new-map" }
},
"OldResourceProperties" : {
"Key1" : "string",
"Key2" : [ "list" ],
"Key3" : { "Key4" : "map" }
}
}
5 changes: 5 additions & 0 deletions lambda-events/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub use event::activemq;
/// AWS Lambda event definitions for alb.
#[cfg(feature = "alb")]
pub use event::alb;

/// AWS Lambda event definitions for apigw.
#[cfg(feature = "apigw")]
pub use event::apigw;
Expand All @@ -40,6 +41,10 @@ pub use event::chime_bot;
#[cfg(feature = "clientvpn")]
pub use event::clientvpn;

/// AWS Lambda event definitions for cloudformation
#[cfg(feature = "cloudformation")]
pub use event::cloudformation;

/// CloudWatch Events payload
#[cfg(feature = "cloudwatch_events")]
pub use event::cloudwatch_events;
Expand Down