Skip to content

Commit

Permalink
add SQS notifciations option (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
morsecodist authored Jan 5, 2022
1 parent 8197d10 commit 1ee4e64
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 7 deletions.
9 changes: 9 additions & 0 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,18 @@ module "sfn" {
stage_memory_defaults = var.stage_memory_defaults
stage_vcpu_defaults = var.stage_vcpu_defaults
extra_env_vars = var.extra_env_vars
sqs_queues = var.sqs_queues
tags = var.tags
}

output "sfn_arns" {
value = module.sfn.sfn_arns
}

output "sfn_notification_queue_arns" {
value = module.sfn.sfn_notification_queue_arns
}

output "sfn_notification_dead_letter_queue_arns" {
value = module.sfn.sfn_notification_dead_letter_queue_arns
}
113 changes: 113 additions & 0 deletions terraform/modules/swipe-sfn/notifications.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# Steps go from top-to-bottom: CloudWatch Event -> SNS topic -> SQS queue ->
# Dead-letter queue (possibly).

resource "aws_cloudwatch_event_rule" "sfn_state_change_rule" {
name = "${var.app_name}-sfn-state-change-rule"
description = "Monitor SFN for status changes."

event_pattern = jsonencode({
source = ["aws.states"]
detail-type = ["Step Functions Execution Status Change"]
detail = {
stateMachineArn = [
for state_machine in aws_sfn_state_machine.swipe_single_wdl :
state_machine.arn
]
}
})
}

resource "aws_cloudwatch_event_target" "sfn_state_change_rule_target" {
rule = aws_cloudwatch_event_rule.sfn_state_change_rule.name
target_id = "SendToSNS"
arn = aws_sns_topic.sfn_notifications_topic.arn
}

resource "aws_sns_topic" "sfn_notifications_topic" {
name = "${var.app_name}-sfn-notifications-topic"

tags = var.tags
}

resource "aws_sns_topic_policy" "sfn_notifications_topic_policy" {
arn = aws_sns_topic.sfn_notifications_topic.arn
policy = data.aws_iam_policy_document.sfn_notifications_topic_policy_document.json
}

data "aws_iam_policy_document" "sfn_notifications_topic_policy_document" {
statement {
effect = "Allow"
actions = ["SNS:Publish"]

principals {
type = "Service"
identifiers = ["events.amazonaws.com"]
}

resources = [aws_sns_topic.sfn_notifications_topic.arn]
}
}

resource "aws_sns_topic_subscription" "sfn_notifications_sqs_target" {
for_each = var.sqs_queues

topic_arn = aws_sns_topic.sfn_notifications_topic.arn
protocol = "sqs"
endpoint = aws_sqs_queue.sfn_notifications_queue[each.key].arn
}

resource "aws_sqs_queue" "sfn_notifications_queue" {
for_each = var.sqs_queues

name = "${var.app_name}-${each.key}-sfn-notifications-queue"

// Upper-bound for handling any notification
visibility_timeout_seconds = lookup(each.value, "visibility_timeout_seconds", "120")

// Sent to dead-letter queue after maxReceiveCount tries
redrive_policy = lookup(each.value, "dead_letter", "true") == "true" ? null : jsonencode({
deadLetterTargetArn = aws_sqs_queue.sfn_notifications_queue_dead_letter[each.key].arn
maxReceiveCount = 3
})

tags = var.tags
}

resource "aws_sqs_queue_policy" "sfn_notifications_queue_policy" {
for_each = var.sqs_queues

queue_url = aws_sqs_queue.sfn_notifications_queue[each.key].id

policy = data.aws_iam_policy_document.sfn_notifications_queue_policy_document[each.key].json
}

data "aws_iam_policy_document" "sfn_notifications_queue_policy_document" {
for_each = var.sqs_queues

statement {
effect = "Allow"
actions = ["sqs:SendMessage"]

principals {
type = "Service"
identifiers = ["sns.amazonaws.com"]
}

resources = [aws_sqs_queue.sfn_notifications_queue[each.key].arn]

condition {
test = "ArnEquals"
variable = "aws:SourceArn"

values = [aws_sns_topic.sfn_notifications_topic.arn]
}
}
}

resource "aws_sqs_queue" "sfn_notifications_queue_dead_letter" {
for_each = { for name, opts in var.sqs_queues : name => opts if lookup(opts, "dead_letter", "true") == "true" }

name = "${var.app_name}-${each.key}-sfn-notifications-queue-dead-letter"

tags = var.tags
}
8 changes: 8 additions & 0 deletions terraform/modules/swipe-sfn/outputs.tf
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
output "sfn_arns" {
value = { for name, sfn in aws_sfn_state_machine.swipe_single_wdl : name => sfn.arn }
}

output "sfn_notification_queue_arns" {
value = { for name, queue in aws_sqs_queue.sfn_notifications_queue : name => queue.arn }
}

output "sfn_notification_dead_letter_queue_arns" {
value = { for name, queue in aws_sqs_queue.sfn_notifications_queue_dead_letter : name => queue.arn }
}
5 changes: 5 additions & 0 deletions terraform/modules/swipe-sfn/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,11 @@ variable "extra_env_vars" {
type = map(string)
}

variable "sqs_queues" {
description = "A dictionary of sqs queue names to a map of options: visibility_timeout_seconds (default: '120'), dead_letter ('true'/'false' default: 'true')"
type = map(map(string))
}

variable "tags" {
description = "Tags to apply to managed assets"
type = map(string)
Expand Down
14 changes: 8 additions & 6 deletions test/mock.tf
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
provider "aws" {
endpoints {
stepfunctions = "http://localhost:8083"
batch = "http://localhost:9000"
iam = "http://localhost:9000"
ec2 = "http://localhost:9000"
lambda = "http://localhost:9000"
cloudwatch = "http://localhost:9000"
cloudwatchevents = "http://localhost:9000"
ec2 = "http://localhost:9000"
iam = "http://localhost:9000"
lambda = "http://localhost:9000"
s3 = "http://localhost:9000"
sts = "http://localhost:9000"
ssm = "http://localhost:9000"
secretsmanager = "http://localhost:9000"
sns = "http://localhost:9000"
sqs = "http://localhost:9000"
ssm = "http://localhost:9000"
stepfunctions = "http://localhost:8083"
sts = "http://localhost:9000"
}
}
6 changes: 6 additions & 0 deletions variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ variable "extra_env_vars" {
default = {}
}

variable "sqs_queues" {
description = "A dictionary of sqs queue names to a map of options: visibility_timeout_seconds (default: '120'), dead_letter ('true'/'false' default: 'true')"
type = map(map(string))
default = {}
}

variable "tags" {
description = "Tags to apply to managed assets"
type = map(string)
Expand Down
2 changes: 1 addition & 1 deletion version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
v0.8.0-beta
v0.9.0-beta

0 comments on commit 1ee4e64

Please sign in to comment.